diff --git a/pdns/credentials.cc b/pdns/credentials.cc index ec11732f246c..a1131035d128 100644 --- a/pdns/credentials.cc +++ b/pdns/credentials.cc @@ -56,10 +56,6 @@ static std::string const pwhash_prefix = "$scrypt$"; static size_t const pwhash_prefix_size = pwhash_prefix.size(); #endif -uint64_t const CredentialsHolder::s_defaultWorkFactor{1024U}; /* N */ -uint64_t const CredentialsHolder::s_defaultParallelFactor{1U}; /* p */ -uint64_t const CredentialsHolder::s_defaultBlockSize{8U}; /* r */ - SensitiveData::SensitiveData(std::string&& data) : d_data(std::move(data)) { diff --git a/pdns/credentials.hh b/pdns/credentials.hh index 6762b1a84511..1cadc14b8b99 100644 --- a/pdns/credentials.hh +++ b/pdns/credentials.hh @@ -81,9 +81,9 @@ public: static bool isHashingAvailable(); static SensitiveData readFromTerminal(); - static uint64_t const s_defaultWorkFactor; - static uint64_t const s_defaultParallelFactor; - static uint64_t const s_defaultBlockSize; + static uint64_t constexpr s_defaultWorkFactor{1024U}; /* N */; + static uint64_t constexpr s_defaultParallelFactor{1U}; /* p */; + static uint64_t constexpr s_defaultBlockSize{8U}; /* r */; private: SensitiveData d_credentials; diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 2ca88419c789..98267217f8a2 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -150,6 +150,7 @@ dnsdist_SOURCES = \ dnsdist-cache.cc dnsdist-cache.hh \ dnsdist-carbon.cc dnsdist-carbon.hh \ dnsdist-concurrent-connections.hh \ + dnsdist-configuration.cc dnsdist-configuration.hh \ dnsdist-console.cc dnsdist-console.hh \ dnsdist-crypto.cc dnsdist-crypto.hh \ dnsdist-discovery.cc dnsdist-discovery.hh \ @@ -194,6 +195,7 @@ dnsdist_SOURCES = \ dnsdist-protobuf.cc dnsdist-protobuf.hh \ dnsdist-protocols.cc dnsdist-protocols.hh \ dnsdist-proxy-protocol.cc dnsdist-proxy-protocol.hh \ + dnsdist-query-count.hh dnsdist-query-count.cc \ dnsdist-random.cc dnsdist-random.hh \ dnsdist-resolver.cc dnsdist-resolver.hh \ dnsdist-rings.cc dnsdist-rings.hh \ @@ -274,6 +276,7 @@ testrunner_SOURCES = \ dnsdist-backoff.hh \ dnsdist-cache.cc dnsdist-cache.hh \ dnsdist-concurrent-connections.hh \ + dnsdist-configuration.cc dnsdist-configuration.hh \ dnsdist-crypto.cc dnsdist-crypto.hh \ dnsdist-dnsparser.cc dnsdist-dnsparser.hh \ dnsdist-doh-common.cc dnsdist-doh-common.hh \ @@ -547,6 +550,7 @@ fuzz_target_dnsdistcache_SOURCES = \ channel.hh channel.cc \ dns.cc dns.hh \ dnsdist-cache.cc dnsdist-cache.hh \ + dnsdist-configuration.cc dnsdist-configuration.hh \ dnsdist-dnsparser.cc dnsdist-dnsparser.hh \ dnsdist-ecs.cc dnsdist-ecs.hh \ dnsdist-idstate.hh \ diff --git a/pdns/dnsdistdist/dnscrypt.hh b/pdns/dnsdistdist/dnscrypt.hh index ff5e40bbdfba..516848f9a05d 100644 --- a/pdns/dnsdistdist/dnscrypt.hh +++ b/pdns/dnsdistdist/dnscrypt.hh @@ -259,7 +259,7 @@ public: void getCertificateResponse(time_t now, PacketBuffer& response) const; int encryptResponse(PacketBuffer& response, size_t maxResponseSize, bool tcp); - static const size_t s_minUDPLength = 256; + static constexpr size_t s_minUDPLength = 256; private: static void fillServerNonce(DNSCryptNonceType& nonce); diff --git a/pdns/dnsdistdist/dnsdist-backend.cc b/pdns/dnsdistdist/dnsdist-backend.cc index 54c4fc76e7ba..781b0c7ae49d 100644 --- a/pdns/dnsdistdist/dnsdist-backend.cc +++ b/pdns/dnsdistdist/dnsdist-backend.cc @@ -26,6 +26,7 @@ #include "dnsdist-nghttp2.hh" #include "dnsdist-random.hh" #include "dnsdist-rings.hh" +#include "dnsdist-snmp.hh" #include "dnsdist-tcp.hh" #include "dnsdist-xsk.hh" #include "dolog.hh" @@ -143,7 +144,7 @@ bool DownstreamState::reconnect(bool initialAttempt) connected = true; } catch (const std::runtime_error& error) { - if (initialAttempt || g_verbose) { + if (initialAttempt || dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose) { infolog("Error connecting to new server with address %s: %s", d_config.remote.toStringWithPort(), error.what()); } connected = false; @@ -236,6 +237,7 @@ void DownstreamState::stop() void DownstreamState::hash() { vinfolog("Computing hashes for id=%s and weight=%d", *d_config.id, d_config.d_weight); + const auto hashPerturbation = dnsdist::configuration::getImmutableConfiguration().d_hashPerturbation; auto w = d_config.d_weight; auto idStr = boost::str(boost::format("%s") % *d_config.id); auto lockedHashes = hashes.write_lock(); @@ -243,7 +245,8 @@ void DownstreamState::hash() lockedHashes->reserve(w); while (w > 0) { std::string uuid = boost::str(boost::format("%s-%d") % idStr % w); - unsigned int wshash = burtleCI(reinterpret_cast(uuid.c_str()), uuid.size(), g_hashperturb); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): sorry, it's the burtle API + unsigned int wshash = burtleCI(reinterpret_cast(uuid.c_str()), uuid.size(), hashPerturbation); lockedHashes->push_back(wshash); --w; } @@ -305,7 +308,7 @@ DownstreamState::DownstreamState(DownstreamState::Config&& config, std::shared_p #ifdef HAVE_NGHTTP2 setupDoHClientProtocolNegotiation(d_tlsCtx); - if (g_configurationDone && g_outgoingDoHWorkerThreads && *g_outgoingDoHWorkerThreads == 0) { + if (dnsdist::configuration::isConfigurationDone() && g_outgoingDoHWorkerThreads && *g_outgoingDoHWorkerThreads == 0) { throw std::runtime_error("Error: setOutgoingDoHWorkerThreads() is set to 0 so no outgoing DoH worker thread is available to serve queries"); } @@ -352,11 +355,12 @@ void DownstreamState::start() void DownstreamState::connectUDPSockets() { - if (s_randomizeIDs) { + const auto& config = dnsdist::configuration::getImmutableConfiguration(); + if (config.d_randomizeIDsToBackend) { idStates.clear(); } else { - idStates.resize(g_maxOutstanding); + idStates.resize(config.d_maxUDPOutstanding); } sockets.resize(d_config.d_numberOfSockets); @@ -396,8 +400,8 @@ int DownstreamState::pickSocketForSending() return sockets[0]; } - size_t idx; - if (s_randomizeSockets) { + size_t idx{0}; + if (dnsdist::configuration::getImmutableConfiguration().d_randomizeUDPSocketsToBackend) { idx = dnsdist::getRandomValue(numberOfSockets); } else { @@ -419,14 +423,10 @@ void DownstreamState::pickSocketsReadyForReceiving(std::vector& ready) (*mplexer.lock())->getAvailableFDs(ready, 1000); } -bool DownstreamState::s_randomizeSockets{false}; -bool DownstreamState::s_randomizeIDs{false}; -int DownstreamState::s_udpTimeout{2}; - -static bool isIDSExpired(const IDState& ids) +static bool isIDSExpired(const IDState& ids, uint8_t udpTimeout) { auto age = ids.age.load(); - return age > DownstreamState::s_udpTimeout; + return age > udpTimeout; } void DownstreamState::handleUDPTimeout(IDState& ids) @@ -478,11 +478,13 @@ void DownstreamState::handleUDPTimeouts() return; } - if (s_randomizeIDs) { + const auto& config = dnsdist::configuration::getImmutableConfiguration(); + const auto udpTimeout = config.d_udpTimeout; + if (config.d_randomizeIDsToBackend) { auto map = d_idStatesMap.lock(); for (auto it = map->begin(); it != map->end(); ) { auto& ids = it->second; - if (isIDSExpired(ids)) { + if (isIDSExpired(ids, udpTimeout)) { handleUDPTimeout(ids); it = map->erase(it); continue; @@ -497,7 +499,7 @@ void DownstreamState::handleUDPTimeouts() if (!ids.isInUse()) { continue; } - if (!isIDSExpired(ids)) { + if (!isIDSExpired(ids, udpTimeout)) { ++ids.age; continue; } @@ -506,7 +508,7 @@ void DownstreamState::handleUDPTimeouts() continue; } /* check again, now that we have locked this state */ - if (ids.isInUse() && isIDSExpired(ids)) { + if (ids.isInUse() && isIDSExpired(ids, udpTimeout)) { handleUDPTimeout(ids); } } @@ -516,7 +518,8 @@ void DownstreamState::handleUDPTimeouts() uint16_t DownstreamState::saveState(InternalQueryState&& state) { - if (s_randomizeIDs) { + const auto& config = dnsdist::configuration::getImmutableConfiguration(); + if (config.d_randomizeIDsToBackend) { /* if the state is already in use we will retry, up to 5 five times. The last selected one is used even if it was already in use */ @@ -578,7 +581,8 @@ uint16_t DownstreamState::saveState(InternalQueryState&& state) void DownstreamState::restoreState(uint16_t id, InternalQueryState&& state) { - if (s_randomizeIDs) { + const auto& config = dnsdist::configuration::getImmutableConfiguration(); + if (config.d_randomizeIDsToBackend) { auto map = d_idStatesMap.lock(); auto [it, inserted] = map->emplace(id, IDState()); @@ -619,8 +623,8 @@ void DownstreamState::restoreState(uint16_t id, InternalQueryState&& state) std::optional DownstreamState::getState(uint16_t id) { std::optional result = std::nullopt; - - if (s_randomizeIDs) { + const auto& config = dnsdist::configuration::getImmutableConfiguration(); + if (config.d_randomizeIDsToBackend) { auto map = d_idStatesMap.lock(); auto it = map->find(id); @@ -864,7 +868,7 @@ void DownstreamState::submitHealthCheckResult(bool initial, bool newResult) } setUpStatus(newState); - if (g_snmpAgent && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendBackendStatusChangeTrap(*this); } } diff --git a/pdns/dnsdistdist/dnsdist-carbon.cc b/pdns/dnsdistdist/dnsdist-carbon.cc index 2be36ed3827b..5ffe257e0b59 100644 --- a/pdns/dnsdistdist/dnsdist-carbon.cc +++ b/pdns/dnsdistdist/dnsdist-carbon.cc @@ -26,6 +26,7 @@ #include "dnsdist-carbon.hh" #include "dnsdist.hh" #include "dnsdist-backoff.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-metrics.hh" #ifndef DISABLE_CARBON @@ -270,7 +271,7 @@ static bool doOneCarbonExport(const Carbon::Endpoint& endpoint) { std::string qname; - auto records = g_qcount.records.write_lock(); + auto records = dnsdist::QueryCount::g_queryCountRecords.write_lock(); for (const auto& record : *records) { qname = record.first; boost::replace_all(qname, ".", "_"); diff --git a/pdns/dnsdistdist/dnsdist-concurrent-connections.hh b/pdns/dnsdistdist/dnsdist-concurrent-connections.hh index 3cf55d5a414d..9827bbc33fec 100644 --- a/pdns/dnsdistdist/dnsdist-concurrent-connections.hh +++ b/pdns/dnsdistdist/dnsdist-concurrent-connections.hh @@ -24,6 +24,7 @@ #include #include "iputils.hh" #include "lock.hh" +#include "dnsdist-configuration.hh" namespace dnsdist { @@ -32,12 +33,13 @@ class IncomingConcurrentTCPConnectionsManager public: static bool accountNewTCPConnection(const ComboAddress& from) { - if (s_maxTCPConnectionsPerClient == 0) { + const auto maxConnsPerClient = dnsdist::configuration::getImmutableConfiguration().d_maxTCPConnectionsPerClient; + if (maxConnsPerClient == 0) { return true; } auto db = s_tcpClientsConcurrentConnectionsCount.lock(); auto& count = (*db)[from]; - if (count >= s_maxTCPConnectionsPerClient) { + if (count >= maxConnsPerClient) { return false; } ++count; @@ -46,7 +48,8 @@ public: static void accountClosedTCPConnection(const ComboAddress& from) { - if (s_maxTCPConnectionsPerClient == 0) { + const auto maxConnsPerClient = dnsdist::configuration::getImmutableConfiguration().d_maxTCPConnectionsPerClient; + if (maxConnsPerClient == 0) { return; } auto db = s_tcpClientsConcurrentConnectionsCount.lock(); @@ -57,14 +60,8 @@ public: } } - static void setMaxTCPConnectionsPerClient(size_t max) - { - s_maxTCPConnectionsPerClient = max; - } - private: static LockGuarded> s_tcpClientsConcurrentConnectionsCount; - static size_t s_maxTCPConnectionsPerClient; }; } diff --git a/pdns/dnsdistdist/dnsdist-configuration.cc b/pdns/dnsdistdist/dnsdist-configuration.cc new file mode 100644 index 000000000000..24689ea0d5ba --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-configuration.cc @@ -0,0 +1,66 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-configuration.hh" +#include "sholder.hh" + +namespace dnsdist::configuration +{ +static GlobalStateHolder s_currentRuntimeConfiguration; +static Configuration s_configuration; +static std::atomic s_configurationDone{false}; + +const RuntimeConfiguration& getCurrentRuntimeConfiguration() +{ + static thread_local auto t_threadLocalConfiguration = s_currentRuntimeConfiguration.getLocal(); + return *t_threadLocalConfiguration; +} + +void updateRuntimeConfiguration(const std::function& mutator) +{ + s_currentRuntimeConfiguration.modify(mutator); +} + +void updateImmutableConfiguration(const std::function& mutator) +{ + if (isConfigurationDone()) { + throw std::runtime_error("Trying to update an immutable setting at runtime!"); + } + + mutator(s_configuration); +} + +const Configuration& getImmutableConfiguration() +{ + return s_configuration; +} + +bool isConfigurationDone() +{ + return s_configurationDone.load(); +} + +void setConfigurationDone() +{ + s_configurationDone.store(true); +} +} diff --git a/pdns/dnsdistdist/dnsdist-configuration.hh b/pdns/dnsdistdist/dnsdist-configuration.hh new file mode 100644 index 000000000000..01c3dd4b37aa --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-configuration.hh @@ -0,0 +1,222 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include +#include +#include + +#include "dnsdist-query-count.hh" +#include "iputils.hh" + +/* so what could you do: + drop, + fake up nxdomain, + provide actual answer, + allow & and stop processing, + continue processing, + modify header: (servfail|refused|notimp), set TC=1, + send to pool */ + +struct DNSQuestion; +struct DNSResponse; + +class DNSAction +{ +public: + enum class Action : uint8_t + { + Drop, + Nxdomain, + Refused, + Spoof, + Allow, + HeaderModify, + Pool, + Delay, + Truncate, + ServFail, + None, + NoOp, + NoRecurse, + SpoofRaw, + SpoofPacket, + SetTag, + }; + static std::string typeToString(const Action& action) + { + switch (action) { + case Action::Drop: + return "Drop"; + case Action::Nxdomain: + return "Send NXDomain"; + case Action::Refused: + return "Send Refused"; + case Action::Spoof: + return "Spoof an answer"; + case Action::SpoofPacket: + return "Spoof a raw answer from bytes"; + case Action::SpoofRaw: + return "Spoof an answer from raw bytes"; + case Action::Allow: + return "Allow"; + case Action::HeaderModify: + return "Modify the header"; + case Action::Pool: + return "Route to a pool"; + case Action::Delay: + return "Delay"; + case Action::Truncate: + return "Truncate over UDP"; + case Action::ServFail: + return "Send ServFail"; + case Action::SetTag: + return "Set Tag"; + case Action::None: + case Action::NoOp: + return "Do nothing"; + case Action::NoRecurse: + return "Set rd=0"; + } + + return "Unknown"; + } + + virtual Action operator()(DNSQuestion*, std::string* ruleresult) const = 0; + virtual ~DNSAction() = default; + virtual std::string toString() const = 0; + virtual std::map getStats() const + { + return {{}}; + } + virtual void reload() + { + } +}; + +class DNSResponseAction +{ +public: + enum class Action : uint8_t + { + Allow, + Delay, + Drop, + HeaderModify, + ServFail, + Truncate, + None + }; + virtual Action operator()(DNSResponse*, std::string* ruleresult) const = 0; + virtual ~DNSResponseAction() = default; + virtual std::string toString() const = 0; + virtual void reload() + { + } +}; + +namespace dnsdist::configuration +{ +/* when we add EDNS to a query, we don't want to advertise + a large buffer size */ +static constexpr size_t s_EdnsUDPPayloadSize{512}; +static constexpr uint16_t s_defaultPayloadSizeSelfGenAnswers = 1232; +static constexpr uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value +static_assert(s_defaultPayloadSizeSelfGenAnswers < s_udpIncomingBufferSize, "The UDP responder's payload size should be smaller or equal to our incoming buffer size"); + +struct Configuration +{ + std::string d_consoleKey; +#ifdef __linux__ + // On Linux this gives us 128k pending queries (default is 8192 queries), + // which should be enough to deal with huge spikes + uint64_t d_maxTCPQueuedConnections{10000}; + size_t d_tcpInternalPipeBufferSize{1048576U}; +#else + uint64_t d_maxTCPQueuedConnections{1000}; + size_t d_tcpInternalPipeBufferSize{0}; +#endif + double d_weightedBalancingFactor{0}; + double d_consistentHashBalancingFactor{0}; + uint64_t d_maxTCPClientThreads{0}; + size_t d_maxTCPConnectionsPerClient{0}; + size_t d_udpVectorSize{1}; + uint32_t d_socketUDPSendBuffer{0}; + uint32_t d_socketUDPRecvBuffer{0}; + uint32_t d_hashPerturbation{0}; + uint16_t d_maxUDPOutstanding{std::numeric_limits::max()}; + uint8_t d_udpTimeout{2}; + bool d_randomizeUDPSocketsToBackend{false}; + bool d_randomizeIDsToBackend{false}; +}; + +struct RuntimeConfiguration +{ + NetmaskGroup d_proxyProtocolACL; + NetmaskGroup d_consoleACL; + dnsdist::QueryCount::Configuration d_queryCountConfig; + std::string d_secPollSuffix{"secpoll.powerdns.com."}; + std::string d_apiConfigDirectory; + size_t d_maxTCPQueriesPerConn{0}; + size_t d_maxTCPConnectionDuration{0}; + size_t d_proxyProtocolMaximumSize{512}; + uint32_t d_staleCacheEntriesTTL{0}; + uint32_t d_secPollInterval{3600}; + uint32_t d_consoleOutputMsgMaxSize{10000000}; + uint16_t d_payloadSizeSelfGenAnswers{s_defaultPayloadSizeSelfGenAnswers}; + uint16_t d_tcpRecvTimeout{2}; + uint16_t d_tcpSendTimeout{2}; + /* rfc7871: "11.1. Privacy" */ + uint16_t d_ECSSourcePrefixV4{24}; + uint16_t d_ECSSourcePrefixV6{56}; + uint16_t d_cacheCleaningDelay{60}; + uint16_t d_cacheCleaningPercentage{100}; + uint16_t d_tlsSessionCacheCleanupDelay{60}; + uint16_t d_tlsSessionCacheSessionValidity{600}; + uint16_t d_tlsSessionCacheMaxSessionsPerBackend{20}; + DNSAction::Action d_dynBlockAction{DNSAction::Action::Drop}; + bool d_truncateTC{false}; + bool d_fixupCase{false}; + bool d_queryCountEnabled{false}; + bool d_ecsOverride{false}; + bool d_verbose{false}; + bool d_verboseHealthChecks{false}; + bool d_apiReadWrite{false}; + bool d_roundrobinFailOnNoServer{false}; + bool d_servFailOnNoPolicy{false}; + bool d_allowEmptyResponse{false}; + bool d_dropEmptyQueries{false}; + bool d_snmpEnabled{false}; + bool d_snmpTrapsEnabled{false}; + bool d_consoleEnabled{false}; + bool d_logConsoleConnections{true}; + bool d_addEDNSToSelfGeneratedResponses{true}; + bool d_applyACLToProxiedClients{false}; +}; + +const RuntimeConfiguration& getCurrentRuntimeConfiguration(); +const Configuration& getImmutableConfiguration(); +void updateImmutableConfiguration(const std::function& mutator); +void updateRuntimeConfiguration(const std::function& mutator); +bool isConfigurationDone(); +void setConfigurationDone(); +} diff --git a/pdns/dnsdistdist/dnsdist-console.cc b/pdns/dnsdistdist/dnsdist-console.cc index 6696843fd91e..77dee4e812b4 100644 --- a/pdns/dnsdistdist/dnsdist-console.cc +++ b/pdns/dnsdistdist/dnsdist-console.cc @@ -46,12 +46,7 @@ #include "dnsdist-crypto.hh" #include "threadname.hh" -GlobalStateHolder g_consoleACL; -vector> g_confDelta; -std::string g_consoleKey; -bool g_logConsoleConnections{true}; -bool g_consoleEnabled{false}; -uint32_t g_consoleOutputMsgMaxSize{10000000}; +static LockGuarded>> s_confDelta; static ConcurrentConnectionManager s_connManager(100); @@ -101,7 +96,6 @@ void setConsoleMaximumConcurrentConnections(size_t max) s_connManager.setMaxConcurrentConnections(max); } -// MUST BE CALLED UNDER A LOCK - right now the LuaLock static void feedConfigDelta(const std::string& line) { if (line.empty()) { @@ -109,7 +103,15 @@ static void feedConfigDelta(const std::string& line) } timeval now{}; gettimeofday(&now, nullptr); - g_confDelta.emplace_back(now, line); + s_confDelta.lock()->emplace_back(now, line); +} + +namespace dnsdist::console +{ +const std::vector>& getConfigurationDelta() +{ + return *(s_confDelta.lock()); +} } #ifdef HAVE_LIBEDIT @@ -156,7 +158,7 @@ static ConsoleCommandResult getMsgLen32(int fileDesc, uint32_t* len) } *len = ntohl(raw); - if (*len > g_consoleOutputMsgMaxSize) { + if (*len > dnsdist::configuration::getCurrentRuntimeConfiguration().d_consoleOutputMsgMaxSize) { return ConsoleCommandResult::TooLarge; } @@ -181,7 +183,8 @@ static bool putMsgLen32(int fileDesc, uint32_t len) static ConsoleCommandResult sendMessageToServer(int fileDesc, const std::string& line, dnsdist::crypto::authenticated::Nonce& readingNonce, dnsdist::crypto::authenticated::Nonce& writingNonce, const bool outputEmptyLine) { - string msg = dnsdist::crypto::authenticated::encryptSym(line, g_consoleKey, writingNonce); + const auto& consoleKey = dnsdist::configuration::getImmutableConfiguration().d_consoleKey; + string msg = dnsdist::crypto::authenticated::encryptSym(line, consoleKey, writingNonce); const auto msgLen = msg.length(); if (msgLen > std::numeric_limits::max()) { cerr << "Encrypted message is too long to be sent to the server, " << std::to_string(msgLen) << " > " << std::numeric_limits::max() << endl; @@ -201,7 +204,7 @@ static ConsoleCommandResult sendMessageToServer(int fileDesc, const std::string& return commandResult; } if (commandResult == ConsoleCommandResult::TooLarge) { - cerr << "Received a console message whose length (" << len << ") is exceeding the allowed one (" << g_consoleOutputMsgMaxSize << "), closing that connection" << endl; + cerr << "Received a console message whose length (" << len << ") is exceeding the allowed one (" << dnsdist::configuration::getCurrentRuntimeConfiguration().d_consoleOutputMsgMaxSize << "), closing that connection" << endl; return commandResult; } @@ -216,7 +219,7 @@ static ConsoleCommandResult sendMessageToServer(int fileDesc, const std::string& msg.clear(); msg.resize(len); readn2(fileDesc, msg.data(), len); - msg = dnsdist::crypto::authenticated::decryptSym(msg, g_consoleKey, readingNonce); + msg = dnsdist::crypto::authenticated::decryptSym(msg, consoleKey, readingNonce); cout << msg; cout.flush(); @@ -225,12 +228,13 @@ static ConsoleCommandResult sendMessageToServer(int fileDesc, const std::string& void doClient(ComboAddress server, const std::string& command) { - if (!dnsdist::crypto::authenticated::isValidKey(g_consoleKey)) { + const auto& consoleKey = dnsdist::configuration::getImmutableConfiguration().d_consoleKey; + if (!dnsdist::crypto::authenticated::isValidKey(consoleKey)) { cerr << "The currently configured console key is not valid, please configure a valid key using the setKey() directive" << endl; return; } - if (g_verbose) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose) { cout << "Connecting to " << server.toStringWithPort() << endl; } @@ -902,6 +906,7 @@ static void controlClientThread(ConsoleConnection&& conn) setTCPNoDelay(conn.getFD()); + const auto& consoleKey = dnsdist::configuration::getImmutableConfiguration().d_consoleKey; dnsdist::crypto::authenticated::Nonce theirs; dnsdist::crypto::authenticated::Nonce ours; dnsdist::crypto::authenticated::Nonce readingNonce; @@ -929,7 +934,7 @@ static void controlClientThread(ConsoleConnection&& conn) line.resize(len); readn2(conn.getFD(), line.data(), len); - line = dnsdist::crypto::authenticated::decryptSym(line, g_consoleKey, readingNonce); + line = dnsdist::crypto::authenticated::decryptSym(line, consoleKey, readingNonce); string response; try { @@ -1021,11 +1026,11 @@ static void controlClientThread(ConsoleConnection&& conn) catch (const LuaContext::SyntaxErrorException& e) { response = "Error: " + string(e.what()) + ": "; } - response = dnsdist::crypto::authenticated::encryptSym(response, g_consoleKey, writingNonce); + response = dnsdist::crypto::authenticated::encryptSym(response, consoleKey, writingNonce); putMsgLen32(conn.getFD(), response.length()); writen2(conn.getFD(), response.c_str(), response.length()); } - if (g_logConsoleConnections) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_logConsoleConnections) { infolog("Closed control connection from %s", conn.getClient().toStringWithPort()); } } @@ -1046,25 +1051,25 @@ void controlThread(std::shared_ptr acceptFD, ComboAddress local) client.sin4.sin_family = local.sin4.sin_family; int sock{-1}; - auto localACL = g_consoleACL.getLocal(); infolog("Accepting control connections on %s", local.toStringWithPort()); while ((sock = SAccept(acceptFD->getHandle(), client)) >= 0) { - + const auto& consoleKey = dnsdist::configuration::getImmutableConfiguration().d_consoleKey; FDWrapper socket(sock); - if (!dnsdist::crypto::authenticated::isValidKey(g_consoleKey)) { + if (!dnsdist::crypto::authenticated::isValidKey(consoleKey)) { vinfolog("Control connection from %s dropped because we don't have a valid key configured, please configure one using setKey()", client.toStringWithPort()); continue; } - if (!localACL->match(client)) { + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (!runtimeConfig.d_consoleACL.match(client)) { vinfolog("Control connection from %s dropped because of ACL", client.toStringWithPort()); continue; } try { ConsoleConnection conn(client, std::move(socket)); - if (g_logConsoleConnections) { + if (runtimeConfig.d_logConsoleConnections) { warnlog("Got control connection from %s", client.toStringWithPort()); } @@ -1086,5 +1091,5 @@ void clearConsoleHistory() #ifdef HAVE_LIBEDIT clear_history(); #endif /* HAVE_LIBEDIT */ - g_confDelta.clear(); + s_confDelta.lock()->clear(); } diff --git a/pdns/dnsdistdist/dnsdist-console.hh b/pdns/dnsdistdist/dnsdist-console.hh index dd833c49e473..077fc2609ce6 100644 --- a/pdns/dnsdistdist/dnsdist-console.hh +++ b/pdns/dnsdistdist/dnsdist-console.hh @@ -21,6 +21,9 @@ */ #pragma once +#include +#include + #include "config.h" #include "sstuff.hh" @@ -50,15 +53,14 @@ extern "C" #endif /* DISABLE_COMPLETION */ -extern GlobalStateHolder g_consoleACL; -extern std::string g_consoleKey; // in theory needs locking -extern bool g_logConsoleConnections; -extern bool g_consoleEnabled; -extern uint32_t g_consoleOutputMsgMaxSize; - void doClient(ComboAddress server, const std::string& command); void doConsole(); void controlThread(std::shared_ptr acceptFD, ComboAddress local); void clearConsoleHistory(); void setConsoleMaximumConcurrentConnections(size_t max); + +namespace dnsdist::console +{ +const std::vector>& getConfigurationDelta(); +} diff --git a/pdns/dnsdistdist/dnsdist-discovery.cc b/pdns/dnsdistdist/dnsdist-discovery.cc index bba713bb6f43..ed2a76653834 100644 --- a/pdns/dnsdistdist/dnsdist-discovery.cc +++ b/pdns/dnsdistdist/dnsdist-discovery.cc @@ -235,6 +235,7 @@ static bool handleSVCResult(const PacketBuffer& answer, const ComboAddress& exis bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeableBackend, ServiceDiscovery::DiscoveredResolverConfig& config) { + const auto verbose = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose; const auto& backend = upgradeableBackend.d_ds; const auto& addr = backend->d_config.remote; try { @@ -276,7 +277,7 @@ bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeable uint16_t responseSize = 0; auto got = readn2WithTimeout(sock.getHandle(), &responseSize, sizeof(responseSize), remainingTime); if (got != sizeof(responseSize)) { - if (g_verbose) { + if (verbose) { warnlog("Error while waiting for the ADD upgrade response size from backend %s: %d", addr.toStringWithPort(), got); } return false; @@ -286,14 +287,14 @@ bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeable got = readn2WithTimeout(sock.getHandle(), packet.data(), packet.size(), remainingTime); if (got != packet.size()) { - if (g_verbose) { + if (verbose) { warnlog("Error while waiting for the ADD upgrade response from backend %s: %d", addr.toStringWithPort(), got); } return false; } if (packet.size() <= sizeof(struct dnsheader)) { - if (g_verbose) { + if (verbose) { warnlog("Too short answer of size %d received from the backend %s", packet.size(), addr.toStringWithPort()); } return false; @@ -302,14 +303,14 @@ bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeable struct dnsheader d; memcpy(&d, packet.data(), sizeof(d)); if (d.id != id) { - if (g_verbose) { + if (verbose) { warnlog("Invalid ID (%d / %d) received from the backend %s", d.id, id, addr.toStringWithPort()); } return false; } if (d.rcode != RCode::NoError) { - if (g_verbose) { + if (verbose) { warnlog("Response code '%s' received from the backend %s for '%s'", RCode::to_s(d.rcode), addr.toStringWithPort(), s_discoveryDomain); } @@ -317,7 +318,7 @@ bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeable } if (ntohs(d.qdcount) != 1) { - if (g_verbose) { + if (verbose) { warnlog("Invalid answer (qdcount %d) received from the backend %s", ntohs(d.qdcount), addr.toStringWithPort()); } return false; @@ -328,7 +329,7 @@ bool ServiceDiscovery::getDiscoveredConfig(const UpgradeableBackend& upgradeable DNSName receivedName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &receivedType, &receivedClass); if (receivedName != s_discoveryDomain || receivedType != s_discoveryType || receivedClass != QClass::IN) { - if (g_verbose) { + if (verbose) { warnlog("Invalid answer, either the qname (%s / %s), qtype (%s / %s) or qclass (%s / %s) does not match, received from the backend %s", receivedName, s_discoveryDomain, QType(receivedType).toString(), s_discoveryType.toString(), QClass(receivedClass).toString(), QClass::IN.toString(), addr.toStringWithPort()); } return false; diff --git a/pdns/dnsdistdist/dnsdist-dynblocks.cc b/pdns/dnsdistdist/dnsdist-dynblocks.cc index ec9362d58729..1b276003b1f6 100644 --- a/pdns/dnsdistdist/dnsdist-dynblocks.cc +++ b/pdns/dnsdistdist/dnsdist-dynblocks.cc @@ -5,7 +5,6 @@ GlobalStateHolder> g_dynblockNMG; GlobalStateHolder> g_dynblockSMT; -DNSAction::Action g_dynBlockAction = DNSAction::Action::Drop; #ifndef DISABLE_DYNBLOCKS void DynBlockRulesGroup::apply(const timespec& now) @@ -202,14 +201,14 @@ bool DynBlockRulesGroup::checkIfResponseCodeMatches(const Rings::Response& respo /* return the actual action that will be taken by that block: - either the one set on that block, if any - - or the one set with setDynBlocksAction in g_dynBlockAction + - or the one set with setDynBlocksAction */ static DNSAction::Action getActualAction(const DynBlock& block) { if (block.action != DNSAction::Action::None) { return block.action; } - return g_dynBlockAction; + return dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction; } namespace dnsdist::DynamicBlocks diff --git a/pdns/dnsdistdist/dnsdist-ecs.cc b/pdns/dnsdistdist/dnsdist-ecs.cc index 988345640745..c3fe0bccc2ce 100644 --- a/pdns/dnsdistdist/dnsdist-ecs.cc +++ b/pdns/dnsdistdist/dnsdist-ecs.cc @@ -28,20 +28,6 @@ #include "ednsoptions.hh" #include "ednssubnet.hh" -/* when we add EDNS to a query, we don't want to advertise - a large buffer size */ -size_t g_EdnsUDPPayloadSize = 512; -static const uint16_t defaultPayloadSizeSelfGenAnswers = 1232; -static_assert(defaultPayloadSizeSelfGenAnswers < s_udpIncomingBufferSize, "The UDP responder's payload size should be smaller or equal to our incoming buffer size"); -uint16_t g_PayloadSizeSelfGenAnswers{defaultPayloadSizeSelfGenAnswers}; - -/* draft-ietf-dnsop-edns-client-subnet-04 "11.1. Privacy" */ -uint16_t g_ECSSourcePrefixV4 = 24; -uint16_t g_ECSSourcePrefixV6 = 56; - -bool g_ECSOverride{false}; -bool g_addEDNSToSelfGeneratedResponses{true}; - int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent) { if (initialPacket.size() < sizeof(dnsheader)) { @@ -261,7 +247,7 @@ bool slowRewriteEDNSOptionInQueryWithRecords(const PacketBuffer& initialPacket, } if (ednsAdded) { - packetWriter.addOpt(g_EdnsUDPPayloadSize, 0, 0, {{optionToReplace, std::string(&newOptionContent.at(EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), newOptionContent.size() - (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE))}}, 0); + packetWriter.addOpt(dnsdist::configuration::s_EdnsUDPPayloadSize, 0, 0, {{optionToReplace, std::string(&newOptionContent.at(EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), newOptionContent.size() - (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE))}}, 0); optionAdded = true; } @@ -585,7 +571,7 @@ static bool addECSToExistingOPT(PacketBuffer& packet, size_t maximumSize, const static bool addEDNSWithECS(PacketBuffer& packet, size_t maximumSize, const string& newECSOption, bool& ednsAdded, bool& ecsAdded) { - if (!generateOptRR(newECSOption, packet, maximumSize, g_EdnsUDPPayloadSize, 0, false)) { + if (!generateOptRR(newECSOption, packet, maximumSize, dnsdist::configuration::s_EdnsUDPPayloadSize, 0, false)) { return false; } @@ -918,7 +904,7 @@ bool setNegativeAndAdditionalSOA(DNSQuestion& dnsQuestion, bool nxd, const DNSNa bool hadEDNS = false; bool dnssecOK = false; - if (g_addEDNSToSelfGeneratedResponses) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses) { uint16_t payloadSize = 0; uint16_t zValue = 0; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) @@ -997,7 +983,7 @@ bool setNegativeAndAdditionalSOA(DNSQuestion& dnsQuestion, bool nxd, const DNSNa if (hadEDNS) { /* now we need to add a new OPT record */ - return addEDNS(packet, dnsQuestion.getMaximumSize(), dnssecOK, g_PayloadSizeSelfGenAnswers, dnsQuestion.ednsRCode); + return addEDNS(packet, dnsQuestion.getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, dnsQuestion.ednsRCode); } return true; @@ -1036,9 +1022,9 @@ bool addEDNSToQueryTurnedResponse(DNSQuestion& dnsQuestion) return true; }); - if (g_addEDNSToSelfGeneratedResponses) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses) { /* now we need to add a new OPT record */ - return addEDNS(packet, dnsQuestion.getMaximumSize(), dnssecOK, g_PayloadSizeSelfGenAnswers, dnsQuestion.ednsRCode); + return addEDNS(packet, dnsQuestion.getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, dnsQuestion.ednsRCode); } /* otherwise we are just fine */ @@ -1150,7 +1136,7 @@ bool setEDNSOption(DNSQuestion& dnsQuestion, uint16_t ednsCode, const std::strin } auto& data = dnsQuestion.getMutableData(); - if (generateOptRR(optRData, data, dnsQuestion.getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) { + if (generateOptRR(optRData, data, dnsQuestion.getMaximumSize(), dnsdist::configuration::s_EdnsUDPPayloadSize, 0, false)) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [](dnsheader& header) { header.arcount = htons(1); return true; @@ -1196,7 +1182,7 @@ bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uint buffer.resize(sizeof(dnsheader) + qnameLength + sizeof(uint16_t) + sizeof(uint16_t)); if (hadEDNS) { DNSQuestion dnsQuestion(state, buffer); - if (!addEDNS(buffer, dnsQuestion.getMaximumSize(), (edns0.extFlags & htons(EDNS_HEADER_FLAG_DO)) != 0, g_PayloadSizeSelfGenAnswers, 0)) { + if (!addEDNS(buffer, dnsQuestion.getMaximumSize(), (edns0.extFlags & htons(EDNS_HEADER_FLAG_DO)) != 0, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, 0)) { return false; } } diff --git a/pdns/dnsdistdist/dnsdist-ecs.hh b/pdns/dnsdistdist/dnsdist-ecs.hh index 94eccc1a1d7b..ee901bee97b6 100644 --- a/pdns/dnsdistdist/dnsdist-ecs.hh +++ b/pdns/dnsdistdist/dnsdist-ecs.hh @@ -31,9 +31,6 @@ struct DNSQuestion; // root label (1), type (2), class (2), ttl (4) + rdlen (2) static const size_t optRecordMinimumSize = 11; -extern size_t g_EdnsUDPPayloadSize; -extern uint16_t g_PayloadSizeSelfGenAnswers; - int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent); bool slowRewriteEDNSOptionInQueryWithRecords(const PacketBuffer& initialPacket, PacketBuffer& newContent, bool& ednsAdded, uint16_t optionToReplace, bool& optionAdded, bool overrideExisting, const string& newOptionContent); int locateEDNSOptRR(const PacketBuffer& packet, uint16_t* optStart, size_t* optLen, bool* last); diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.cc b/pdns/dnsdistdist/dnsdist-healthchecks.cc index 36805573e784..02c08037461a 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.cc +++ b/pdns/dnsdistdist/dnsdist-healthchecks.cc @@ -29,8 +29,6 @@ #include "dnsdist-nghttp2.hh" #include "dnsdist-session-cache.hh" -bool g_verboseHealthChecks{false}; - struct HealthCheckData { enum class TCPState : uint8_t @@ -66,11 +64,12 @@ struct HealthCheckData static bool handleResponse(std::shared_ptr& data) { + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; const auto& downstream = data->d_ds; try { if (data->d_buffer.size() < sizeof(dnsheader)) { ++data->d_ds->d_healthCheckMetrics.d_parseErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Invalid health check response of size %d from backend %s, expecting at least %d", data->d_buffer.size(), downstream->getNameWithAddr(), sizeof(dnsheader)); } return false; @@ -79,7 +78,7 @@ static bool handleResponse(std::shared_ptr& data) dnsheader_aligned responseHeader(data->d_buffer.data()); if (responseHeader.get()->id != data->d_queryID) { ++data->d_ds->d_healthCheckMetrics.d_mismatchErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Invalid health check response id %d from backend %s, expecting %d", responseHeader.get()->id, downstream->getNameWithAddr(), data->d_queryID); } return false; @@ -87,7 +86,7 @@ static bool handleResponse(std::shared_ptr& data) if (!responseHeader.get()->qr) { ++data->d_ds->d_healthCheckMetrics.d_invalidResponseErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Invalid health check response from backend %s, expecting QR to be set", downstream->getNameWithAddr()); } return false; @@ -95,7 +94,7 @@ static bool handleResponse(std::shared_ptr& data) if (responseHeader.get()->rcode == RCode::ServFail) { ++data->d_ds->d_healthCheckMetrics.d_invalidResponseErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Backend %s responded to health check with ServFail", downstream->getNameWithAddr()); } return false; @@ -103,7 +102,7 @@ static bool handleResponse(std::shared_ptr& data) if (downstream->d_config.mustResolve && (responseHeader.get()->rcode == RCode::NXDomain || responseHeader.get()->rcode == RCode::Refused)) { ++data->d_ds->d_healthCheckMetrics.d_invalidResponseErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Backend %s responded to health check with %s while mustResolve is set", downstream->getNameWithAddr(), responseHeader.get()->rcode == RCode::NXDomain ? "NXDomain" : "Refused"); } return false; @@ -116,7 +115,7 @@ static bool handleResponse(std::shared_ptr& data) if (receivedName != data->d_checkName || receivedType != data->d_checkType || receivedClass != data->d_checkClass) { ++data->d_ds->d_healthCheckMetrics.d_mismatchErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Backend %s responded to health check with an invalid qname (%s vs %s), qtype (%s vs %s) or qclass (%d vs %d)", downstream->getNameWithAddr(), receivedName.toLogString(), data->d_checkName.toLogString(), QType(receivedType).toString(), QType(data->d_checkType).toString(), receivedClass, data->d_checkClass); } return false; @@ -124,13 +123,13 @@ static bool handleResponse(std::shared_ptr& data) } catch (const std::exception& e) { ++data->d_ds->d_healthCheckMetrics.d_parseErrors; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error checking the health of backend %s: %s", downstream->getNameWithAddr(), e.what()); } return false; } catch (...) { - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Unknown exception while checking the health of backend %s", downstream->getNameWithAddr()); } return false; @@ -181,6 +180,7 @@ class HealthCheckQuerySender : public TCPQuerySender static void healthCheckUDPCallback(int descriptor, FDMultiplexer::funcparam_t& param) { auto data = boost::any_cast>(param); + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; ssize_t got = 0; ComboAddress from; @@ -202,7 +202,7 @@ static void healthCheckUDPCallback(int descriptor, FDMultiplexer::funcparam_t& p return; } - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error receiving health check response from %s: %s", data->d_ds->d_config.remote.toStringWithPort(), stringerror(savederrno)); } ++data->d_ds->d_healthCheckMetrics.d_networkErrors; @@ -216,7 +216,7 @@ static void healthCheckUDPCallback(int descriptor, FDMultiplexer::funcparam_t& p /* we are using a connected socket but hey.. */ if (from != data->d_ds->d_config.remote) { - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Invalid health check response received from %s, expecting one from %s", from.toStringWithPort(), data->d_ds->d_config.remote.toStringWithPort()); } ++data->d_ds->d_healthCheckMetrics.d_networkErrors; @@ -288,13 +288,15 @@ static void healthCheckTCPCallback(int descriptor, FDMultiplexer::funcparam_t& p catch (const std::exception& e) { ++data->d_ds->d_healthCheckMetrics.d_networkErrors; data->d_ds->submitHealthCheckResult(data->d_initial, false); - if (g_verboseHealthChecks) { + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; + if (verboseHealthChecks) { infolog("Error checking the health of backend %s: %s", data->d_ds->getNameWithAddr(), e.what()); } } catch (...) { data->d_ds->submitHealthCheckResult(data->d_initial, false); - if (g_verboseHealthChecks) { + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; + if (verboseHealthChecks) { infolog("Unknown exception while checking the health of backend %s", data->d_ds->getNameWithAddr()); } } @@ -302,6 +304,7 @@ static void healthCheckTCPCallback(int descriptor, FDMultiplexer::funcparam_t& p bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared_ptr& downstream, bool initialCheck) { + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; try { uint16_t queryID = dnsdist::getRandomDNSID(); DNSName checkName = downstream->d_config.checkName; @@ -350,7 +353,7 @@ bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared #ifdef SO_BINDTODEVICE if (!downstream->d_config.sourceItfName.empty()) { int res = setsockopt(sock.getHandle(), SOL_SOCKET, SO_BINDTODEVICE, downstream->d_config.sourceItfName.c_str(), downstream->d_config.sourceItfName.length()); - if (res != 0 && g_verboseHealthChecks) { + if (res != 0 && verboseHealthChecks) { infolog("Error setting SO_BINDTODEVICE on the health check socket for backend '%s': %s", downstream->getNameWithAddr(), stringerror()); } } @@ -382,7 +385,7 @@ bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared ssize_t sent = udpClientSendRequestToBackend(downstream, data->d_udpSocket.getHandle(), packet, true); if (sent < 0) { int ret = errno; - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while sending a health check query (ID %d) to backend %s: %d", queryID, downstream->getNameWithAddr(), ret); } return false; @@ -435,13 +438,13 @@ bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared return true; } catch (const std::exception& e) { - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error checking the health of backend %s: %s", downstream->getNameWithAddr(), e.what()); } return false; } catch (...) { - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Unknown exception while checking the health of backend %s", downstream->getNameWithAddr()); } return false; @@ -450,13 +453,14 @@ bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial) { + const auto verboseHealthChecks = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verboseHealthChecks; while (mplexer.getWatchedFDCount(false) > 0 || mplexer.getWatchedFDCount(true) > 0) { struct timeval now { }; int ret = mplexer.run(&now, 100); if (ret == -1) { - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while waiting for the health check response from backends: %d", ret); } break; @@ -485,7 +489,7 @@ void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial) else { mplexer.removeReadFD(timeout.first); } - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Timeout while waiting for the health check response (ID %d) from backend %s", data->d_queryID, data->d_ds->getNameWithAddr()); } @@ -496,13 +500,13 @@ void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial) /* this is not supposed to happen as the file descriptor has to be there for us to reach that code, and the submission code should not throw, but let's provide a nice error message if it ever does. */ - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while dealing with a timeout for the health check response (ID %d) from backend %s: %s", data->d_queryID, data->d_ds->getNameWithAddr(), e.what()); } } catch (...) { /* this is even less likely to happen */ - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while dealing with a timeout for the health check response (ID %d) from backend %s", data->d_queryID, data->d_ds->getNameWithAddr()); } } @@ -517,7 +521,7 @@ void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial) try { /* UDP does not block while writing, H2 is handled separately */ data->d_ioState.reset(); - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Timeout while waiting for the health check response (ID %d) from backend %s", data->d_queryID, data->d_ds->getNameWithAddr()); } @@ -527,13 +531,13 @@ void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial) catch (const std::exception& e) { /* this is not supposed to happen as the submission code should not throw, but let's provide a nice error message if it ever does. */ - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while dealing with a timeout for the health check response (ID %d) from backend %s: %s", data->d_queryID, data->d_ds->getNameWithAddr(), e.what()); } } catch (...) { /* this is even less likely to happen */ - if (g_verboseHealthChecks) { + if (verboseHealthChecks) { infolog("Error while dealing with a timeout for the health check response (ID %d) from backend %s", data->d_queryID, data->d_ds->getNameWithAddr()); } } diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.hh b/pdns/dnsdistdist/dnsdist-healthchecks.hh index e9da6c66de8b..fa3cf57aa818 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.hh +++ b/pdns/dnsdistdist/dnsdist-healthchecks.hh @@ -25,7 +25,5 @@ #include "mplexer.hh" #include "sstuff.hh" -extern bool g_verboseHealthChecks; - bool queueHealthCheck(std::unique_ptr& mplexer, const std::shared_ptr& downstream, bool initial = false); void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial = false); diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.cc b/pdns/dnsdistdist/dnsdist-lbpolicies.cc index b4e3532619ac..99d1f9036b18 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.cc +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.cc @@ -28,7 +28,6 @@ #include "dns_random.hh" GlobalStateHolder g_policy; -bool g_roundrobinFailOnNoServer{false}; static constexpr size_t s_staticArrayCutOff = 16; template using DynamicIndexArray = std::vector>; @@ -84,16 +83,15 @@ shared_ptr firstAvailable(const ServerPolicy::NumberedServerVec return leastOutstanding(servers, dq); } -double g_weightedBalancingFactor = 0; - template static std::shared_ptr getValRandom(const ServerPolicy::NumberedServerVector& servers, T& poss, const unsigned int val, const double targetLoad) { constexpr int max = std::numeric_limits::max(); int sum = 0; size_t usableServers = 0; + const auto weightedBalancingFactor = dnsdist::configuration::getImmutableConfiguration().d_consistentHashBalancingFactor; for (const auto& d : servers) { // w=1, w=10 -> 1, 11 - if (d.second->isUp() && (g_weightedBalancingFactor == 0 || (d.second->outstanding <= (targetLoad * d.second->d_config.d_weight)))) { + if (d.second->isUp() && (weightedBalancingFactor == 0 || (static_cast(d.second->outstanding.load()) <= (targetLoad * d.second->d_config.d_weight)))) { // Don't overflow sum when adding high weights if (d.second->d_config.d_weight > max - sum) { sum = max; @@ -125,8 +123,8 @@ static shared_ptr valrandom(const unsigned int val, const Serve { using ValRandomType = int; double targetLoad = std::numeric_limits::max(); - - if (g_weightedBalancingFactor > 0) { + const auto weightedBalancingFactor = dnsdist::configuration::getImmutableConfiguration().d_consistentHashBalancingFactor; + if (weightedBalancingFactor > 0) { /* we start with one, representing the query we are currently handling */ double currentLoad = 1; size_t totalWeight = 0; @@ -138,7 +136,7 @@ static shared_ptr valrandom(const unsigned int val, const Serve } if (totalWeight > 0) { - targetLoad = (currentLoad / totalWeight) * g_weightedBalancingFactor; + targetLoad = (currentLoad / static_cast(totalWeight)) * weightedBalancingFactor; } } @@ -157,9 +155,6 @@ shared_ptr wrandom(const ServerPolicy::NumberedServerVector& se return valrandom(dns_random_uint32(), servers); } -uint32_t g_hashperturb; -double g_consistentHashBalancingFactor = 0; - shared_ptr whashedFromHash(const ServerPolicy::NumberedServerVector& servers, size_t hash) { return valrandom(hash, servers); @@ -167,7 +162,8 @@ shared_ptr whashedFromHash(const ServerPolicy::NumberedServerVe shared_ptr whashed(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq) { - return whashedFromHash(servers, dq->ids.qname.hash(g_hashperturb)); + const auto hashPerturbation = dnsdist::configuration::getImmutableConfiguration().d_hashPerturbation; + return whashedFromHash(servers, dq->ids.qname.hash(hashPerturbation)); } shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVector& servers, size_t qhash) @@ -177,7 +173,8 @@ shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVe shared_ptr ret = nullptr, first = nullptr; double targetLoad = std::numeric_limits::max(); - if (g_consistentHashBalancingFactor > 0) { + const auto consistentHashBalancingFactor = dnsdist::configuration::getImmutableConfiguration().d_consistentHashBalancingFactor; + if (consistentHashBalancingFactor > 0) { /* we start with one, representing the query we are currently handling */ double currentLoad = 1; size_t totalWeight = 0; @@ -189,12 +186,12 @@ shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVe } if (totalWeight > 0) { - targetLoad = (currentLoad / totalWeight) * g_consistentHashBalancingFactor; + targetLoad = (currentLoad / totalWeight) * consistentHashBalancingFactor; } } for (const auto& d: servers) { - if (d.second->isUp() && (g_consistentHashBalancingFactor == 0 || d.second->outstanding <= (targetLoad * d.second->d_config.d_weight))) { + if (d.second->isUp() && (consistentHashBalancingFactor == 0 || static_cast(d.second->outstanding.load()) <= (targetLoad * d.second->d_config.d_weight))) { // make sure hashes have been computed if (!d.second->hashesComputed) { d.second->hash(); @@ -229,7 +226,8 @@ shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVe shared_ptr chashed(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq) { - return chashedFromHash(servers, dq->ids.qname.hash(g_hashperturb)); + const auto hashPerturbation = dnsdist::configuration::getImmutableConfiguration().d_hashPerturbation; + return chashedFromHash(servers, dq->ids.qname.hash(hashPerturbation)); } shared_ptr roundrobin(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq) @@ -248,7 +246,7 @@ shared_ptr roundrobin(const ServerPolicy::NumberedServerVector& } if (candidates.empty()) { - if (g_roundrobinFailOnNoServer) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_roundrobinFailOnNoServer) { return shared_ptr(); } for (auto& d : servers) { diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.hh b/pdns/dnsdistdist/dnsdist-lbpolicies.hh index 78fcb22016b2..fd943b249821 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.hh +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.hh @@ -110,8 +110,3 @@ std::shared_ptr whashedFromHash(const ServerPolicy::NumberedSer std::shared_ptr chashed(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq); std::shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVector& servers, size_t hash); std::shared_ptr roundrobin(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq); - -extern double g_consistentHashBalancingFactor; -extern double g_weightedBalancingFactor; -extern uint32_t g_hashperturb; -extern bool g_roundrobinFailOnNoServer; diff --git a/pdns/dnsdistdist/dnsdist-lua-actions.cc b/pdns/dnsdistdist/dnsdist-lua-actions.cc index ebb82507a4b5..760715ede198 100644 --- a/pdns/dnsdistdist/dnsdist-lua-actions.cc +++ b/pdns/dnsdistdist/dnsdist-lua-actions.cc @@ -33,6 +33,7 @@ #include "dnsdist-proxy-protocol.hh" #include "dnsdist-kvs.hh" #include "dnsdist-rule-chains.hh" +#include "dnsdist-snmp.hh" #include "dnsdist-svc.hh" #include "dnstap.hh" @@ -254,7 +255,7 @@ std::map TeeAction::getStats() const void TeeAction::worker() { setThreadName("dnsdist/TeeWork"); - std::array packet{}; + std::array packet{}; ssize_t res = 0; const dnsheader_aligned dnsheader(packet.data()); for (;;) { @@ -453,6 +454,7 @@ class SpoofSVCAction : public DNSAction if (!dnsdist::svc::generateSVCResponse(*dnsquestion, d_payloads, d_additionals4, d_additionals6, d_responseConfig)) { return Action::None; } + return Action::HeaderModify; } @@ -905,7 +907,8 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dnsquestion, std::string* bool dnssecOK = false; bool hadEDNS = false; - if (g_addEDNSToSelfGeneratedResponses && queryHasEDNS(*dnsquestion)) { + const auto& runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (runtimeConfiguration.d_addEDNSToSelfGeneratedResponses && queryHasEDNS(*dnsquestion)) { hadEDNS = true; dnssecOK = ((getEDNSZ(*dnsquestion) & EDNS_HEADER_FLAG_DO) != 0); } @@ -1008,7 +1011,7 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dnsquestion, std::string* }); if (hadEDNS && !raw) { - addEDNS(dnsquestion->getMutableData(), dnsquestion->getMaximumSize(), dnssecOK, g_PayloadSizeSelfGenAnswers, 0); + addEDNS(dnsquestion->getMutableData(), dnsquestion->getMaximumSize(), dnssecOK, runtimeConfiguration.d_payloadSizeSelfGenAnswers, 0); } return Action::HeaderModify; @@ -1058,7 +1061,7 @@ class SetMacAddrAction : public DNSAction } auto& data = dnsquestion->getMutableData(); - if (generateOptRR(optRData, data, dnsquestion->getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) { + if (generateOptRR(optRData, data, dnsquestion->getMaximumSize(), dnsdist::configuration::s_EdnsUDPPayloadSize, 0, false)) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [](dnsheader& header) { header.arcount = htons(1); return true; @@ -1143,7 +1146,7 @@ class LogAction : public DNSAction, public boost::noncopyable { auto filepointer = std::atomic_load_explicit(&d_fp, std::memory_order_acquire); if (!filepointer) { - if (!d_verboseOnly || g_verbose) { + if (!d_verboseOnly || dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose) { if (d_includeTimestamp) { infolog("[%u.%u] Packet from %s for %s %s with id %d", static_cast(dnsquestion->getQueryRealTime().tv_sec), static_cast(dnsquestion->getQueryRealTime().tv_nsec), dnsquestion->ids.origRemote.toStringWithPort(), dnsquestion->ids.qname.toString(), QType(dnsquestion->ids.qtype).toString(), dnsquestion->getHeader()->id); } @@ -1255,7 +1258,7 @@ class LogResponseAction : public DNSResponseAction, public boost::noncopyable { auto filepointer = std::atomic_load_explicit(&d_fp, std::memory_order_acquire); if (!filepointer) { - if (!d_verboseOnly || g_verbose) { + if (!d_verboseOnly || dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose) { if (d_includeTimestamp) { infolog("[%u.%u] Answer to %s for %s %s (%s) with id %u", static_cast(response->getQueryRealTime().tv_sec), static_cast(response->getQueryRealTime().tv_nsec), response->ids.origRemote.toStringWithPort(), response->ids.qname.toString(), QType(response->ids.qtype).toString(), RCode::to_s(response->getHeader()->rcode), response->getHeader()->id); } @@ -1712,7 +1715,7 @@ class SNMPTrapAction : public DNSAction } DNSAction::Action operator()(DNSQuestion* dnsquestion, std::string* ruleresult) const override { - if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(*dnsquestion, d_reason); } @@ -1919,7 +1922,7 @@ class SNMPTrapResponseAction : public DNSResponseAction } DNSResponseAction::Action operator()(DNSResponse* response, std::string* ruleresult) const override { - if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(*response, d_reason); } diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc index 9297dbccad81..8889fea67458 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc @@ -25,6 +25,7 @@ #include "dnsdist-ecs.hh" #include "dnsdist-internal-queries.hh" #include "dnsdist-lua.hh" +#include "dnsdist-snmp.hh" #include "dnsparser.hh" // NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold @@ -169,7 +170,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) luaCtx.registerFunction("sendTrap", [](const DNSQuestion& dnsQuestion, boost::optional reason) { #ifdef HAVE_NET_SNMP - if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(dnsQuestion, reason ? *reason : ""); } #endif /* HAVE_NET_SNMP */ @@ -496,7 +497,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) luaCtx.registerFunction("sendTrap", [](const DNSResponse& dnsResponse, boost::optional reason) { #ifdef HAVE_NET_SNMP - if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(dnsResponse, reason ? *reason : ""); } #endif /* HAVE_NET_SNMP */ diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings.cc b/pdns/dnsdistdist/dnsdist-lua-bindings.cc index de53de97dba5..29abfcda486d 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings.cc @@ -669,7 +669,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.registerFunction::*)()>("attachToAllBinds", [](std::shared_ptr& bpf) { std::string res; - if (!g_configurationDone) { + if (!dnsdist::configuration::isConfigurationDone()) { throw std::runtime_error("attachToAllBinds() cannot be used at configuration time!"); return; } @@ -737,7 +737,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) #ifdef HAVE_XSK using xskopt_t = LuaAssociativeTable>; luaCtx.writeFunction("newXsk", [client](xskopt_t opts) { - if (g_configurationDone) { + if (dnsdist::configuration::isConfigurationDone()) { throw std::runtime_error("newXsk() only can be used at configuration time!"); } if (client) { diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 1443fa9e7784..f3dcd72453fb 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -32,6 +32,7 @@ #include "dnsdist-ecs.hh" #include "dnsdist-rings.hh" #include "dnsdist-svc.hh" +#include "dnsdist-snmp.hh" #include "dolog.hh" uint16_t dnsdist_ffi_dnsquestion_get_qtype(const dnsdist_ffi_dnsquestion_t* dq) @@ -585,7 +586,7 @@ bool dnsdist_ffi_dnsquestion_set_trailing_data(dnsdist_ffi_dnsquestion_t* dq, co void dnsdist_ffi_dnsquestion_send_trap(dnsdist_ffi_dnsquestion_t* dq, const char* reason, size_t reasonLen) { - if (g_snmpAgent && g_snmpTrapsEnabled) { + if (g_snmpAgent != nullptr && dnsdist::configuration::getCurrentRuntimeConfiguration().d_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(*dq->dq, std::string(reason, reasonLen)); } } @@ -1961,7 +1962,7 @@ size_t dnsdist_ffi_dynamic_blocks_get_entries(dnsdist_ffi_dynamic_blocks_list_t* if (g_defaultBPFFilter && details.bpf) { counter += g_defaultBPFFilter->getHits(client.getNetwork()); } - list->d_entries.push_back({strdup(client.toString().c_str()), strdup(details.reason.c_str()), counter, static_cast(details.until.tv_sec - now.tv_sec), static_cast(details.action != DNSAction::Action::None ? details.action : g_dynBlockAction), g_defaultBPFFilter && details.bpf, details.warning}); + list->d_entries.push_back({strdup(client.toString().c_str()), strdup(details.reason.c_str()), counter, static_cast(details.until.tv_sec - now.tv_sec), static_cast(details.action != DNSAction::Action::None ? details.action : dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction), g_defaultBPFFilter && details.bpf, details.warning}); } auto count = list->d_entries.size(); @@ -1982,8 +1983,9 @@ size_t dnsdist_ffi_dynamic_blocks_smt_get_entries(dnsdist_ffi_dynamic_blocks_lis }; gettime(&now); + const auto defaultAction = dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction; auto fullCopy = g_dynblockSMT.getCopy(); - fullCopy.visit([&now, &list](const SuffixMatchTree& node) { + fullCopy.visit([&now, &list, defaultAction](const SuffixMatchTree& node) { if (!(now < node.d_value.until)) { return; } @@ -1993,7 +1995,7 @@ size_t dnsdist_ffi_dynamic_blocks_smt_get_entries(dnsdist_ffi_dynamic_blocks_lis key = entry.domain.toString(); } if (entry.action == DNSAction::Action::None) { - entry.action = g_dynBlockAction; + entry.action = defaultAction; } list->d_entries.push_back({strdup(key.c_str()), strdup(entry.reason.c_str()), entry.blocks, static_cast(entry.until.tv_sec - now.tv_sec), static_cast(entry.action), entry.bpf, entry.warning}); }); diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection.cc b/pdns/dnsdistdist/dnsdist-lua-inspection.cc index d9ac137f45c6..eb8440a3d8de 100644 --- a/pdns/dnsdistdist/dnsdist-lua-inspection.cc +++ b/pdns/dnsdistdist/dnsdist-lua-inspection.cc @@ -22,8 +22,9 @@ #include #include "dnsdist.hh" -#include "dnsdist-lua.hh" +#include "dnsdist-console.hh" #include "dnsdist-dynblocks.hh" +#include "dnsdist-lua.hh" #include "dnsdist-nghttp2.hh" #include "dnsdist-rings.hh" #include "dnsdist-tcp.hh" @@ -533,7 +534,7 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.writeFunction("delta", []() { setLuaNoSideEffect(); // we hold the lua lock already! - for (const auto& entry : g_confDelta) { + for (const auto& entry : dnsdist::console::getConfigurationDelta()) { tm entryTime{}; localtime_r(&entry.first.tv_sec, &entryTime); std::array date{}; @@ -719,10 +720,11 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.writeFunction("showTCPStats", [] { setLuaNoSideEffect(); + const auto& immutableConfig = dnsdist::configuration::getImmutableConfiguration(); ostringstream ret; boost::format fmt("%-12d %-12d %-12d %-12d"); ret << (fmt % "Workers" % "Max Workers" % "Queued" % "Max Queued") << endl; - ret << (fmt % g_tcpclientthreads->getThreadsCount() % (g_maxTCPClientThreads ? *g_maxTCPClientThreads : 0) % g_tcpclientthreads->getQueuedCount() % g_maxTCPQueuedConnections) << endl; + ret << (fmt % g_tcpclientthreads->getThreadsCount() % immutableConfig.d_maxTCPClientThreads % g_tcpclientthreads->getQueuedCount() % immutableConfig.d_maxTCPQueuedConnections) << endl; ret << endl; ret << "Frontends:" << endl; diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index b611d7c067d8..02187636ee2a 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -39,6 +39,7 @@ #include "dnsdist.hh" #include "dnsdist-carbon.hh" #include "dnsdist-concurrent-connections.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-console.hh" #include "dnsdist-crypto.hh" #include "dnsdist-dynblocks.hh" @@ -57,6 +58,7 @@ #include "dnsdist-rings.hh" #include "dnsdist-secpoll.hh" #include "dnsdist-session-cache.hh" +#include "dnsdist-snmp.hh" #include "dnsdist-tcp-downstream.hh" #include "dnsdist-web.hh" @@ -82,29 +84,28 @@ using std::thread; static boost::optional>> g_launchWork = boost::none; -boost::tribool g_noLuaSideEffect; -static bool g_included{false}; +static boost::tribool s_noLuaSideEffect; /* this is a best effort way to prevent logging calls with no side-effects in the output of delta() Functions can declare setLuaNoSideEffect() and if nothing else does declare a side effect, or nothing has done so before on this invocation, this call won't be part of delta() output */ void setLuaNoSideEffect() { - if (g_noLuaSideEffect == false) { + if (s_noLuaSideEffect == false) { // there has been a side effect already return; } - g_noLuaSideEffect = true; + s_noLuaSideEffect = true; } void setLuaSideEffect() { - g_noLuaSideEffect = false; + s_noLuaSideEffect = false; } bool getLuaNoSideEffect() { - if (g_noLuaSideEffect) { + if (s_noLuaSideEffect) { // NOLINTNEXTLINE(readability-simplify-boolean-expr): it's a tribool, not a boolean return true; } @@ -113,7 +114,7 @@ bool getLuaNoSideEffect() void resetLuaSideEffect() { - g_noLuaSideEffect = boost::logic::indeterminate; + s_noLuaSideEffect = boost::logic::indeterminate; } using localbind_t = LuaAssociativeTable, LuaArray, LuaAssociativeTable, std::shared_ptr>>; @@ -303,7 +304,7 @@ static void LuaThread(const std::string& code) static bool checkConfigurationTime(const std::string& name) { - if (!g_configurationDone) { + if (!dnsdist::configuration::isConfigurationDone()) { return true; } g_outputBuffer = name + " cannot be used at runtime!\n"; @@ -456,7 +457,7 @@ static void handleNewServerSourceParameter(boost::optional& vars, D static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) { luaCtx.writeFunction("inClientStartup", [client]() { - return client && !g_configurationDone; + return client && !dnsdist::configuration::isConfigurationDone(); }); luaCtx.writeFunction("inConfigCheck", [configCheck]() { @@ -649,7 +650,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #ifdef HAVE_XSK LuaArray> luaXskSockets; if (getOptionalValue>>(vars, "xskSockets", luaXskSockets) > 0 && !luaXskSockets.empty()) { - if (g_configurationDone) { + if (dnsdist::configuration::isConfigurationDone()) { throw std::runtime_error("Adding a server with xsk at runtime is not supported"); } std::vector> xskSockets; @@ -753,8 +754,193 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) server->stop(); }); - luaCtx.writeFunction("truncateTC", [](bool value) { setLuaSideEffect(); g_truncateTC = value; }); - luaCtx.writeFunction("fixupCase", [](bool value) { setLuaSideEffect(); g_fixupCase = value; }); + struct BooleanConfigurationItems + { + const std::string name; + const std::function mutator; + }; + static const std::vector booleanConfigItems{ + {"truncateTC", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_truncateTC = newValue; }}, + {"fixupCase", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_fixupCase = newValue; }}, + {"setECSOverride", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_ecsOverride = newValue; }}, + {"setQueryCount", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_queryCountConfig.d_enabled = newValue; }}, + {"setVerbose", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_verbose = newValue; }}, + {"setVerboseHealthChecks", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_verboseHealthChecks = newValue; }}, + {"setServFailWhenNoServer", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_servFailOnNoPolicy = newValue; }}, + {"setRoundRobinFailOnNoServer", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_roundrobinFailOnNoServer = newValue; }}, + {"setDropEmptyQueries", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_dropEmptyQueries = newValue; }}, + {"setAllowEmptyResponse", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_allowEmptyResponse = newValue; }}, + {"setConsoleConnectionsLogging", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_logConsoleConnections = newValue; }}, + {"setProxyProtocolApplyACLToProxiedClients", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_applyACLToProxiedClients = newValue; }}, + {"setAddEDNSToSelfGeneratedResponses", [](dnsdist::configuration::RuntimeConfiguration& config, bool newValue) { config.d_addEDNSToSelfGeneratedResponses = newValue; }}, + }; + struct UnsignedIntegerConfigurationItems + { + const std::string name; + const std::function mutator; + const size_t maximumValue{std::numeric_limits::max()}; + }; + static const std::vector unsignedIntegerConfigItems{ + {"setCacheCleaningDelay", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_cacheCleaningDelay = newValue; }, std::numeric_limits::max()}, + {"setCacheCleaningPercentage", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_cacheCleaningPercentage = newValue; }, 100U}, + {"setOutgoingTLSSessionsCacheMaxTicketsPerBackend", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_tlsSessionCacheMaxSessionsPerBackend = newValue; }, std::numeric_limits::max() }, + {"setOutgoingTLSSessionsCacheCleanupDelay", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_tlsSessionCacheCleanupDelay = newValue; }, std::numeric_limits::max() }, + {"setOutgoingTLSSessionsCacheMaxTicketValidity", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_tlsSessionCacheSessionValidity = newValue; }, std::numeric_limits::max() }, + {"setECSSourcePrefixV4", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_ECSSourcePrefixV4 = newValue; }, std::numeric_limits::max()}, + {"setECSSourcePrefixV6", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_ECSSourcePrefixV6 = newValue; }, std::numeric_limits::max()}, + {"setTCPRecvTimeout", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_tcpRecvTimeout = newValue; }, std::numeric_limits::max()}, + {"setTCPSendTimeout", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_tcpSendTimeout = newValue; }, std::numeric_limits::max()}, + {"setMaxTCPQueriesPerConnection", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_maxTCPQueriesPerConn = newValue; }, std::numeric_limits::max()}, + {"setMaxTCPConnectionDuration", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_maxTCPConnectionDuration = newValue; }, std::numeric_limits::max()}, + {"setStaleCacheEntriesTTL", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_staleCacheEntriesTTL = newValue; }, std::numeric_limits::max()}, + {"setConsoleOutputMaxMsgSize", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_consoleOutputMsgMaxSize = newValue; }, std::numeric_limits::max()}, +#ifndef DISABLE_SECPOLL + {"setSecurityPollInterval", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_secPollInterval = newValue; }, std::numeric_limits::max()}, +#endif /* DISABLE_SECPOLL */ + {"setProxyProtocolMaximumPayloadSize", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { config.d_proxyProtocolMaximumSize = std::max(static_cast(16), newValue); }, std::numeric_limits::max()}, + {"setPayloadSizeOnSelfGeneratedAnswers", [](dnsdist::configuration::RuntimeConfiguration& config, uint64_t newValue) { + if (newValue < 512) { + warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"); + g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"; + newValue = 512; + } + if (newValue > dnsdist::configuration::s_udpIncomingBufferSize) { + warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to %d instead!", dnsdist::configuration::s_udpIncomingBufferSize); + g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to " + std::to_string(dnsdist::configuration::s_udpIncomingBufferSize) + " instead"; + newValue = dnsdist::configuration::s_udpIncomingBufferSize; + } + config.d_payloadSizeSelfGenAnswers = newValue; + }, + std::numeric_limits::max()}, + }; + + struct StringConfigurationItems + { + const std::string name; + const std::function mutator; + }; + static const std::vector stringConfigItems{ +#ifndef DISABLE_SECPOLL + {"setSecurityPollSuffix", [](dnsdist::configuration::RuntimeConfiguration& config, const std::string& newValue) { config.d_secPollSuffix = newValue; }}, +#endif /* DISABLE_SECPOLL */ + }; + + for (const auto& item : booleanConfigItems) { + luaCtx.writeFunction(item.name, [&item](bool value) { + setLuaSideEffect(); + dnsdist::configuration::updateRuntimeConfiguration([value, &item](dnsdist::configuration::RuntimeConfiguration& config) { + item.mutator(config, value); + }); + }); + } + + for (const auto& item : unsignedIntegerConfigItems) { + luaCtx.writeFunction(item.name, [&item](uint64_t value) { + setLuaSideEffect(); + checkParameterBound(item.name, value, item.maximumValue); + dnsdist::configuration::updateRuntimeConfiguration([value, &item](dnsdist::configuration::RuntimeConfiguration& config) { + item.mutator(config, value); + }); + }); + } + + for (const auto& item : stringConfigItems) { + luaCtx.writeFunction(item.name, [&item](const std::string& value) { + setLuaSideEffect(); + dnsdist::configuration::updateRuntimeConfiguration([value, &item](dnsdist::configuration::RuntimeConfiguration& config) { + item.mutator(config, value); + }); + }); + } + + struct BooleanImmutableConfigurationItems + { + const std::string name; + const std::function mutator; + }; + static const std::vector booleanImmutableConfigItems{ + {"setRandomizedOutgoingSockets", [](dnsdist::configuration::Configuration& config, bool newValue) { config.d_randomizeUDPSocketsToBackend = newValue; }}, + {"setRandomizedIdsOverUDP", [](dnsdist::configuration::Configuration& config, bool newValue) { config.d_randomizeIDsToBackend = newValue; }}, + }; + struct UnsignedIntegerImmutableConfigurationItems + { + const std::string name; + const std::function mutator; + const size_t maximumValue{std::numeric_limits::max()}; + }; + static const std::vector unsignedIntegerImmutableConfigItems{ + {"setMaxTCPQueuedConnections", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPQueuedConnections = newValue; }, std::numeric_limits::max()}, + {"setMaxTCPClientThreads", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPClientThreads = newValue; }, std::numeric_limits::max()}, + {"setMaxTCPConnectionsPerClient", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPConnectionsPerClient = newValue; }, std::numeric_limits::max()}, + {"setTCPInternalPipeBufferSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_tcpInternalPipeBufferSize = newValue; }, std::numeric_limits::max()}, + {"setMaxUDPOutstanding", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxUDPOutstanding = newValue; }, std::numeric_limits::max()}, + {"setWHashedPertubation", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_hashPerturbation = newValue; }, std::numeric_limits::max()}, +#ifndef DISABLE_RECVMMSG + {"setUDPMultipleMessagesVectorSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpVectorSize = newValue; }, std::numeric_limits::max()}, +#endif /* DISABLE_RECVMMSG */ + {"setUDPTimeout", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpTimeout = newValue; }, std::numeric_limits::max()}, + }; + struct DoubleImmutableConfigurationItems + { + const std::string name; + const std::function mutator; + const double maximumValue{1.0}; + }; + static const std::vector doubleImmutableConfigItems{ + {"setConsistentHashingBalancingFactor", [](dnsdist::configuration::Configuration& config, double newValue) { config.d_consistentHashBalancingFactor = newValue; }, 1.0}, + {"setWeightedBalancingFactor", [](dnsdist::configuration::Configuration& config, double newValue) { config.d_weightedBalancingFactor = newValue; }, 1.0}, + }; + + for (const auto& item : booleanConfigItems) { + luaCtx.writeFunction(item.name, [&item](bool value) { + try { + dnsdist::configuration::updateRuntimeConfiguration([value, &item](dnsdist::configuration::RuntimeConfiguration& config) { + item.mutator(config, value); + }); + } + catch (const std::exception& exp) { + g_outputBuffer = item.name + " cannot be used at runtime!\n"; + errlog("%s cannot be used at runtime!", item.name); + } + }); + } + + for (const auto& item : unsignedIntegerImmutableConfigItems) { + luaCtx.writeFunction(item.name, [&item](uint64_t value) { + checkParameterBound(item.name, value, item.maximumValue); + try { + dnsdist::configuration::updateImmutableConfiguration([value, &item](dnsdist::configuration::Configuration& config) { + item.mutator(config, value); + }); + } + catch (const std::exception& exp) { + g_outputBuffer = item.name + " cannot be used at runtime!\n"; + errlog("%s cannot be used at runtime!", item.name); + } + }); + } + for (const auto& item : doubleImmutableConfigItems) { + luaCtx.writeFunction(item.name, [&item](double value) { + if (value > item.maximumValue) { + g_outputBuffer = "Invalid value passed to " + item.name + "()!\n"; + errlog("Invalid value passed to %s()!", item.name); + return; + } + + try { + dnsdist::configuration::updateImmutableConfiguration([value, &item](dnsdist::configuration::Configuration& config) { + item.mutator(config, value); + }); + } + catch (const std::exception& exp) { + g_outputBuffer = item.name + " cannot be used at runtime!\n"; + errlog("%s cannot be used at runtime!", item.name); + } + setLuaSideEffect(); + }); + } + + luaCtx.writeFunction("getVerbose", []() { return dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose; }); luaCtx.writeFunction("addACL", [](const std::string& domain) { setLuaSideEffect(); @@ -1194,9 +1380,11 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) return; } - g_consoleEnabled = true; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_consoleEnabled = true; + }); #if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO) - if (g_configurationDone && g_consoleKey.empty()) { + if (dnsdist::configuration::isConfigurationDone() && dnsdist::configuration::getImmutableConfiguration().d_consoleKey.empty()) { warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set"); } #endif @@ -1228,7 +1416,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) warnlog("Allowing remote access to the console while neither libsodium not libcrypto support has been enabled is not secure, and will result in cleartext communications"); #endif - g_consoleACL.modify([netmask](NetmaskGroup& nmg) { nmg.addMask(netmask); }); + dnsdist::configuration::updateRuntimeConfiguration([&netmask](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_consoleACL.addMask(netmask); + }); }); luaCtx.writeFunction("setConsoleACL", [](LuaTypeOrArrayOf inp) { @@ -1247,7 +1437,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) nmg.addMask(entry.second); } } - g_consoleACL.setState(nmg); + dnsdist::configuration::updateRuntimeConfiguration([&nmg](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_consoleACL = std::move(nmg); + }); }); luaCtx.writeFunction("showConsoleACL", []() { @@ -1257,7 +1449,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) warnlog("Allowing remote access to the console while neither libsodium nor libcrypto support has not been enabled is not secure, and will result in cleartext communications"); #endif - auto aclEntries = g_consoleACL.getLocal()->toStringVector(); + auto aclEntries = dnsdist::configuration::getCurrentRuntimeConfiguration().d_consoleACL.toStringVector(); for (const auto& entry : aclEntries) { g_outputBuffer += entry + "\n"; @@ -1272,7 +1464,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("clearQueryCounters", []() { unsigned int size{0}; { - auto records = g_qcount.records.write_lock(); + auto records = dnsdist::QueryCount::g_queryCountRecords.write_lock(); size = records->size(); records->clear(); } @@ -1283,9 +1475,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("getQueryCounters", [](boost::optional optMax) { setLuaNoSideEffect(); - auto records = g_qcount.records.read_lock(); + auto records = dnsdist::QueryCount::g_queryCountRecords.read_lock(); g_outputBuffer = "query counting is currently: "; - g_outputBuffer += g_qcount.enabled ? "enabled" : "disabled"; + g_outputBuffer += dnsdist::configuration::getCurrentRuntimeConfiguration().d_queryCountConfig.d_enabled ? "enabled" : "disabled"; g_outputBuffer += (boost::format(" (%d records in buffer)\n") % records->size()).str(); boost::format fmt("%-3d %s: %d request(s)\n"); @@ -1296,10 +1488,10 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } }); - luaCtx.writeFunction("setQueryCount", [](bool enabled) { g_qcount.enabled = enabled; }); - - luaCtx.writeFunction("setQueryCountFilter", [](QueryCountFilter func) { - g_qcount.filter = std::move(func); + luaCtx.writeFunction("setQueryCountFilter", [](dnsdist::QueryCount::Configuration::Filter func) { + dnsdist::configuration::updateRuntimeConfiguration([&func](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_queryCountConfig.d_filter = std::move(func); + }); }); luaCtx.writeFunction("makeKey", []() { @@ -1308,7 +1500,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); luaCtx.writeFunction("setKey", [](const std::string& key) { - if (!g_configurationDone && !g_consoleKey.empty()) { // this makes sure the commandline -k key prevails over dnsdist.conf + if (!dnsdist::configuration::isConfigurationDone() && !dnsdist::configuration::getImmutableConfiguration().d_consoleKey.empty()) { // this makes sure the commandline -k key prevails over dnsdist.conf return; // but later setKeys() trump the -k value again } #if !defined(HAVE_LIBSODIUM) && !defined(HAVE_LIBCRYPTO) @@ -1316,14 +1508,16 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif setLuaSideEffect(); - string newkey; - if (B64Decode(key, newkey) < 0) { + string newKey; + if (B64Decode(key, newKey) < 0) { g_outputBuffer = string("Unable to decode ") + key + " as Base64"; errlog("%s", g_outputBuffer); + return; } - else { - g_consoleKey = std::move(newkey); - } + + dnsdist::configuration::updateImmutableConfiguration([&newKey](dnsdist::configuration::Configuration& config) { + config.d_consoleKey = std::move(newKey); + }); }); luaCtx.writeFunction("clearConsoleHistory", []() { @@ -1334,6 +1528,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) setLuaNoSideEffect(); #if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO) try { + const auto& consoleKey = dnsdist::configuration::getImmutableConfiguration().d_consoleKey; string testmsg; if (optTestMsg) { @@ -1347,14 +1542,14 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) dnsdist::crypto::authenticated::Nonce nonce2; nonce1.init(); nonce2 = nonce1; - string encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, g_consoleKey, nonce1); - string decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, g_consoleKey, nonce2); + string encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, consoleKey, nonce1); + string decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, consoleKey, nonce2); nonce1.increment(); nonce2.increment(); - encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, g_consoleKey, nonce1); - decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, g_consoleKey, nonce2); + encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, consoleKey, nonce1); + decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, consoleKey, nonce2); if (testmsg == decrypted) { g_outputBuffer = "Everything is ok!\n"; @@ -1374,56 +1569,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) #endif }); - luaCtx.writeFunction("setTCPRecvTimeout", [](int timeout) { g_tcpRecvTimeout = timeout; }); - - luaCtx.writeFunction("setTCPSendTimeout", [](int timeout) { g_tcpSendTimeout = timeout; }); - - luaCtx.writeFunction("setUDPTimeout", [](int timeout) { DownstreamState::s_udpTimeout = timeout; }); - - luaCtx.writeFunction("setMaxUDPOutstanding", [](uint64_t max) { - if (!checkConfigurationTime("setMaxUDPOutstanding")) { - return; - } - - checkParameterBound("setMaxUDPOutstanding", max); - g_maxOutstanding = max; - }); - - luaCtx.writeFunction("setMaxTCPClientThreads", [](uint64_t max) { - if (!checkConfigurationTime("setMaxTCPClientThreads")) { - return; - } - g_maxTCPClientThreads = max; - }); - - luaCtx.writeFunction("setMaxTCPQueuedConnections", [](uint64_t max) { - if (!checkConfigurationTime("setMaxTCPQueuedConnections")) { - return; - } - g_maxTCPQueuedConnections = max; - }); - - luaCtx.writeFunction("setMaxTCPQueriesPerConnection", [](uint64_t max) { - if (!checkConfigurationTime("setMaxTCPQueriesPerConnection")) { - return; - } - g_maxTCPQueriesPerConn = max; - }); - - luaCtx.writeFunction("setMaxTCPConnectionsPerClient", [](uint64_t max) { - if (!checkConfigurationTime("setMaxTCPConnectionsPerClient")) { - return; - } - dnsdist::IncomingConcurrentTCPConnectionsManager::setMaxTCPConnectionsPerClient(max); - }); - - luaCtx.writeFunction("setMaxTCPConnectionDuration", [](uint64_t max) { - if (!checkConfigurationTime("setMaxTCPConnectionDuration")) { - return; - } - g_maxTCPConnectionDuration = max; - }); - luaCtx.writeFunction("setMaxCachedTCPConnectionsPerDownstream", [](uint64_t max) { setTCPDownstreamMaxIdleConnectionsPerBackend(max); }); @@ -1441,61 +1586,15 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); #endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */ - luaCtx.writeFunction("setOutgoingTLSSessionsCacheMaxTicketsPerBackend", [](uint64_t max) { - if (!checkConfigurationTime("setOutgoingTLSSessionsCacheMaxTicketsPerBackend")) { - return; - } - TLSSessionCache::setMaxTicketsPerBackend(max); - }); - - luaCtx.writeFunction("setOutgoingTLSSessionsCacheCleanupDelay", [](time_t delay) { - if (!checkConfigurationTime("setOutgoingTLSSessionsCacheCleanupDelay")) { - return; - } - TLSSessionCache::setCleanupDelay(delay); - }); - - luaCtx.writeFunction("setOutgoingTLSSessionsCacheMaxTicketValidity", [](time_t validity) { - if (!checkConfigurationTime("setOutgoingTLSSessionsCacheMaxTicketValidity")) { - return; - } - TLSSessionCache::setSessionValidity(validity); - }); - luaCtx.writeFunction("getOutgoingTLSSessionCacheSize", []() { setLuaNoSideEffect(); return g_sessionCache.getSize(); }); - luaCtx.writeFunction("setCacheCleaningDelay", [](uint64_t delay) { - checkParameterBound("setCacheCleaningDelay", delay, std::numeric_limits::max()); - g_cacheCleaningDelay = delay; - }); - - luaCtx.writeFunction("setCacheCleaningPercentage", [](uint64_t percentage) { - if (percentage < 100) { - g_cacheCleaningPercentage = percentage; - } - else { - g_cacheCleaningPercentage = 100; - } - }); - - luaCtx.writeFunction("setECSSourcePrefixV4", [](uint64_t prefix) { - checkParameterBound("setECSSourcePrefixV4", prefix, std::numeric_limits::max()); - g_ECSSourcePrefixV4 = prefix; - }); - - luaCtx.writeFunction("setECSSourcePrefixV6", [](uint64_t prefix) { - checkParameterBound("setECSSourcePrefixV6", prefix, std::numeric_limits::max()); - g_ECSSourcePrefixV6 = prefix; - }); - - luaCtx.writeFunction("setECSOverride", [](bool override) { g_ECSOverride = override; }); - #ifndef DISABLE_DYNBLOCKS luaCtx.writeFunction("showDynBlocks", []() { setLuaNoSideEffect(); + const auto runtimeConf = dnsdist::configuration::getCurrentRuntimeConfiguration(); auto slow = g_dynblockNMG.getCopy(); timespec now{}; gettime(&now); @@ -1507,17 +1606,17 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (g_defaultBPFFilter && entry.second.bpf) { counter += g_defaultBPFFilter->getHits(entry.first.getNetwork()); } - g_outputBuffer += (fmt % entry.first.toString() % (entry.second.until.tv_sec - now.tv_sec) % counter % (entry.second.warning ? "true" : "false") % DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : g_dynBlockAction) % (g_defaultBPFFilter && entry.second.bpf ? "*" : "") % entry.second.reason).str(); + g_outputBuffer += (fmt % entry.first.toString() % (entry.second.until.tv_sec - now.tv_sec) % counter % (entry.second.warning ? "true" : "false") % DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : runtimeConf.d_dynBlockAction) % (g_defaultBPFFilter && entry.second.bpf ? "*" : "") % entry.second.reason).str(); } } auto slow2 = g_dynblockSMT.getCopy(); - slow2.visit([&now, &fmt](const SuffixMatchTree& node) { + slow2.visit([&now, &fmt, &runtimeConf](const SuffixMatchTree& node) { if (now < node.d_value.until) { string dom("empty"); if (!node.d_value.domain.empty()) { dom = node.d_value.domain.toString(); } - g_outputBuffer += (fmt % dom % (node.d_value.until.tv_sec - now.tv_sec) % node.d_value.blocks % (node.d_value.warning ? "true" : "false") % DNSAction::typeToString(node.d_value.action != DNSAction::Action::None ? node.d_value.action : g_dynBlockAction) % "" % node.d_value.reason).str(); + g_outputBuffer += (fmt % dom % (node.d_value.until.tv_sec - now.tv_sec) % node.d_value.blocks % (node.d_value.warning ? "true" : "false") % DNSAction::typeToString(node.d_value.action != DNSAction::Action::None ? node.d_value.action : runtimeConf.d_dynBlockAction) % "" % node.d_value.reason).str(); } }); }); @@ -1528,6 +1627,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) gettime(&now); LuaAssociativeTable entries; + const auto defaultAction = dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction; auto fullCopy = g_dynblockNMG.getCopy(); for (const auto& blockPair : fullCopy) { const auto& requestor = blockPair.first; @@ -1539,7 +1639,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) entry.blocks += g_defaultBPFFilter->getHits(requestor.getNetwork()); } if (entry.action == DNSAction::Action::None) { - entry.action = g_dynBlockAction; + entry.action = defaultAction; } entries.emplace(requestor.toString(), std::move(entry)); } @@ -1552,8 +1652,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) gettime(&now); LuaAssociativeTable entries; + const auto defaultAction = dnsdist::configuration::getCurrentRuntimeConfiguration().d_dynBlockAction; auto fullCopy = g_dynblockSMT.getCopy(); - fullCopy.visit([&now, &entries](const SuffixMatchTree& node) { + fullCopy.visit([&now, &entries, defaultAction](const SuffixMatchTree& node) { if (!(now < node.d_value.until)) { return; } @@ -1563,7 +1664,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) key = entry.domain.toString(); } if (entry.action == DNSAction::Action::None) { - entry.action = g_dynBlockAction; + entry.action = defaultAction; } entries.emplace(std::move(key), std::move(entry)); }); @@ -1621,11 +1722,10 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); luaCtx.writeFunction("setDynBlocksAction", [](DNSAction::Action action) { - if (!checkConfigurationTime("setDynBlocksAction")) { - return; - } if (action == DNSAction::Action::Drop || action == DNSAction::Action::NoOp || action == DNSAction::Action::Nxdomain || action == DNSAction::Action::Refused || action == DNSAction::Action::Truncate || action == DNSAction::Action::NoRecurse) { - g_dynBlockAction = action; + dnsdist::configuration::updateRuntimeConfiguration([action](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_dynBlockAction = action; + }); } else { errlog("Dynamic blocks action can only be Drop, NoOp, NXDomain, Refused, Truncate or NoRecurse!"); @@ -1811,9 +1911,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) return pool; }); - luaCtx.writeFunction("setVerbose", [](bool verbose) { g_verbose = verbose; }); - luaCtx.writeFunction("getVerbose", []() { return g_verbose; }); - luaCtx.writeFunction("setVerboseHealthChecks", [](bool verbose) { g_verboseHealthChecks = verbose; }); luaCtx.writeFunction("setVerboseLogDestination", [](const std::string& dest) { if (!checkConfigurationTime("setVerboseLogDestination")) { return; @@ -1848,11 +1945,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) dnsdist::logging::LoggingConfiguration::setStructuredLogging(enable, levelPrefix); }); - luaCtx.writeFunction("setStaleCacheEntriesTTL", [](uint64_t ttl) { - checkParameterBound("setStaleCacheEntriesTTL", ttl, std::numeric_limits::max()); - g_staleCacheEntriesTTL = ttl; - }); - luaCtx.writeFunction("showBinds", []() { setLuaNoSideEffect(); try { @@ -1979,7 +2071,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (!checkConfigurationTime("includeDirectory")) { return; } - if (g_included) { + static bool s_included{false}; + + if (s_included) { errlog("includeDirectory() cannot be used recursively!"); g_outputBuffer = "includeDirectory() cannot be used recursively!\n"; return; @@ -2026,7 +2120,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) std::sort(files.begin(), files.end()); - g_included = true; + s_included = true; for (const auto& file : files) { std::ifstream ifs(file); @@ -2041,62 +2135,29 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.executeCode(ifs); } catch (...) { - g_included = false; + s_included = false; throw; } luaCtx.executeCode(ifs); } - g_included = false; + s_included = false; }); luaCtx.writeFunction("setAPIWritable", [](bool writable, boost::optional apiConfigDir) { - setLuaSideEffect(); - g_apiReadWrite = writable; - if (apiConfigDir) { - if (!(*apiConfigDir).empty()) { - g_apiConfigDirectory = *apiConfigDir; - } - else { - errlog("The API configuration directory value cannot be empty!"); - g_outputBuffer = "The API configuration directory value cannot be empty!"; - } - } - }); - - luaCtx.writeFunction("setServFailWhenNoServer", [](bool servfail) { - setLuaSideEffect(); - g_servFailOnNoPolicy = servfail; - }); - - luaCtx.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) { - setLuaSideEffect(); - g_roundrobinFailOnNoServer = fail; - }); - - luaCtx.writeFunction("setConsistentHashingBalancingFactor", [](double factor) { - setLuaSideEffect(); - if (factor >= 1.0) { - g_consistentHashBalancingFactor = factor; - } - else { - errlog("Invalid value passed to setConsistentHashingBalancingFactor()!"); - g_outputBuffer = "Invalid value passed to setConsistentHashingBalancingFactor()!\n"; + if (apiConfigDir && (*apiConfigDir).empty()) { + errlog("The API configuration directory value cannot be empty!"); + g_outputBuffer = "The API configuration directory value cannot be empty!"; return; } - }); - - luaCtx.writeFunction("setWeightedBalancingFactor", [](double factor) { + dnsdist::configuration::updateRuntimeConfiguration([writable, &apiConfigDir](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_apiReadWrite = writable; + if (!(*apiConfigDir).empty()) { + config.d_apiConfigDirectory = *apiConfigDir; + } + }); setLuaSideEffect(); - if (factor >= 1.0) { - g_weightedBalancingFactor = factor; - } - else { - errlog("Invalid value passed to setWeightedBalancingFactor()!"); - g_outputBuffer = "Invalid value passed to setWeightedBalancingFactor()!\n"; - return; - } }); luaCtx.writeFunction("setRingBuffersSize", [client](uint64_t capacity, boost::optional numberOfShards) { @@ -2136,13 +2197,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } }); - luaCtx.writeFunction("setWHashedPertubation", [](uint64_t perturb) { - setLuaSideEffect(); - checkParameterBound("setWHashedPertubation", perturb, std::numeric_limits::max()); - g_hashperturb = perturb; - }); - - luaCtx.writeFunction("setTCPInternalPipeBufferSize", [](uint64_t size) { g_tcpInternalPipeBufferSize = size; }); luaCtx.writeFunction("setTCPFastOpenKey", [](const std::string& keyString) { setLuaSideEffect(); std::array key{}; @@ -2166,19 +2220,27 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (!checkConfigurationTime("snmpAgent")) { return; } - if (g_snmpEnabled) { - errlog("snmpAgent() cannot be used twice!"); - g_outputBuffer = "snmpAgent() cannot be used twice!\n"; - return; + + { + const auto runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (runtimeConfiguration.d_snmpEnabled) { + errlog("snmpAgent() cannot be used twice!"); + g_outputBuffer = "snmpAgent() cannot be used twice!\n"; + return; + } } - g_snmpEnabled = true; - g_snmpTrapsEnabled = enableTraps; + dnsdist::configuration::updateRuntimeConfiguration([enableTraps](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_snmpEnabled = true; + config.d_snmpTrapsEnabled = enableTraps; + }); + g_snmpAgent = std::make_unique("dnsdist", daemonSocket ? *daemonSocket : std::string()); }); luaCtx.writeFunction("sendCustomTrap", [](const std::string& str) { - if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) { + const auto runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (g_snmpAgent != nullptr && runtimeConfiguration.d_snmpTrapsEnabled) { g_snmpAgent->sendCustomTrap(str); } }); @@ -2281,15 +2343,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); #endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */ - luaCtx.writeFunction("setConsoleConnectionsLogging", [](bool enabled) { - g_logConsoleConnections = enabled; - }); - - luaCtx.writeFunction("setConsoleOutputMaxMsgSize", [](uint64_t size) { - checkParameterBound("setConsoleOutputMaxMsgSize", size, std::numeric_limits::max()); - g_consoleOutputMsgMaxSize = size; - }); - luaCtx.writeFunction("setProxyProtocolACL", [](LuaTypeOrArrayOf inp) { if (!checkConfigurationTime("setProxyProtocolACL")) { return; @@ -2304,56 +2357,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) nmg.addMask(entry.second); } } - g_proxyProtocolACL = std::move(nmg); - }); - - luaCtx.writeFunction("setProxyProtocolApplyACLToProxiedClients", [](bool apply) { - if (!checkConfigurationTime("setProxyProtocolApplyACLToProxiedClients")) { - return; - } - setLuaSideEffect(); - g_applyACLToProxiedClients = apply; - }); - - luaCtx.writeFunction("setProxyProtocolMaximumPayloadSize", [](uint64_t size) { - if (!checkConfigurationTime("setProxyProtocolMaximumPayloadSize")) { - return; - } - setLuaSideEffect(); - g_proxyProtocolMaximumSize = std::max(static_cast(16), size); - }); - -#ifndef DISABLE_RECVMMSG - luaCtx.writeFunction("setUDPMultipleMessagesVectorSize", [](uint64_t vSize) { - if (!checkConfigurationTime("setUDPMultipleMessagesVectorSize")) { - return; - } -#if defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE) - setLuaSideEffect(); - g_udpVectorSize = vSize; -#else - errlog("recvmmsg() support is not available!"); - g_outputBuffer = "recvmmsg support is not available!\n"; -#endif - }); -#endif /* DISABLE_RECVMMSG */ - - luaCtx.writeFunction("setAddEDNSToSelfGeneratedResponses", [](bool add) { - g_addEDNSToSelfGeneratedResponses = add; - }); - - luaCtx.writeFunction("setPayloadSizeOnSelfGeneratedAnswers", [](uint64_t payloadSize) { - if (payloadSize < 512) { - warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"); - g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"; - payloadSize = 512; - } - if (payloadSize > s_udpIncomingBufferSize) { - warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to %d instead!", s_udpIncomingBufferSize); - g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to " + std::to_string(s_udpIncomingBufferSize) + " instead"; - payloadSize = s_udpIncomingBufferSize; - } - g_PayloadSizeSelfGenAnswers = payloadSize; + dnsdist::configuration::updateRuntimeConfiguration([&nmg](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_proxyProtocolACL = std::move(nmg); + }); }); #ifndef DISABLE_SECPOLL @@ -2361,22 +2367,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) setLuaNoSideEffect(); g_outputBuffer = std::to_string(dnsdist::metrics::g_stats.securityStatus) + "\n"; }); - - luaCtx.writeFunction("setSecurityPollSuffix", [](const std::string& suffix) { - if (!checkConfigurationTime("setSecurityPollSuffix")) { - return; - } - g_secPollSuffix = suffix; - }); - - luaCtx.writeFunction("setSecurityPollInterval", [](time_t newInterval) { - if (newInterval <= 0) { - warnlog("setSecurityPollInterval() should be > 0, skipping"); - g_outputBuffer = "setSecurityPollInterval() should be > 0, skipping"; - } - - g_secPollInterval = newInterval; - }); #endif /* DISABLE_SECPOLL */ luaCtx.writeFunction("setSyslogFacility", [](boost::variant facility) { @@ -3294,9 +3284,6 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } }); - luaCtx.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse = allow; }); - luaCtx.writeFunction("setDropEmptyQueries", [](bool drop) { extern bool g_dropEmptyQueries; g_dropEmptyQueries = drop; }); - #if defined(HAVE_LIBSSL) && defined(HAVE_OCSP_BASIC_SIGN) && !defined(DISABLE_OCSP_STAPLING) luaCtx.writeFunction("generateOCSPResponse", [client](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { if (client) { @@ -3326,23 +3313,20 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (client) { return; } - if (!checkConfigurationTime("setUDPSocketBufferSizes")) { - return; - } checkParameterBound("setUDPSocketBufferSizes", recv, std::numeric_limits::max()); checkParameterBound("setUDPSocketBufferSizes", snd, std::numeric_limits::max()); - setLuaSideEffect(); - - g_socketUDPSendBuffer = snd; - g_socketUDPRecvBuffer = recv; - }); - luaCtx.writeFunction("setRandomizedOutgoingSockets", [](bool randomized) { - DownstreamState::s_randomizeSockets = randomized; - }); - - luaCtx.writeFunction("setRandomizedIdsOverUDP", [](bool randomized) { - DownstreamState::s_randomizeIDs = randomized; + try { + dnsdist::configuration::updateImmutableConfiguration([snd, recv](dnsdist::configuration::Configuration& config) { + config.d_socketUDPSendBuffer = snd; + config.d_socketUDPRecvBuffer = recv; + }); + setLuaSideEffect(); + } + catch (const std::exception& exp) { + g_outputBuffer = "setUDPSocketBufferSizes cannot be used at runtime!\n"; + errlog("setUDPSocketBufferSizes cannot be used at runtime!"); + } }); #if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS) diff --git a/pdns/dnsdistdist/dnsdist-nghttp2-in.cc b/pdns/dnsdistdist/dnsdist-nghttp2-in.cc index 797def327e56..089deb52ea58 100644 --- a/pdns/dnsdistdist/dnsdist-nghttp2-in.cc +++ b/pdns/dnsdistdist/dnsdist-nghttp2-in.cc @@ -362,7 +362,8 @@ void IncomingHTTP2Connection::handleIO() gettimeofday(&now, nullptr); try { - if (maxConnectionDurationReached(g_maxTCPConnectionDuration, now)) { + const auto& currentConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (maxConnectionDurationReached(currentConfig.d_maxTCPConnectionDuration, now)) { vinfolog("Terminating DoH connection from %s because it reached the maximum TCP connection duration", d_ci.remote.toStringWithPort()); stopIO(); d_connectionClosing = true; @@ -1154,17 +1155,18 @@ uint32_t IncomingHTTP2Connection::getConcurrentStreamsCount() const boost::optional IncomingHTTP2Connection::getIdleClientReadTTD(struct timeval now) const { + const auto& currentConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); auto idleTimeout = d_ci.cs->dohFrontend->d_idleTimeout; - if (g_maxTCPConnectionDuration == 0 && idleTimeout == 0) { + if (currentConfig.d_maxTCPConnectionDuration == 0 && idleTimeout == 0) { return boost::none; } - if (g_maxTCPConnectionDuration > 0) { + if (currentConfig.d_maxTCPConnectionDuration > 0) { auto elapsed = now.tv_sec - d_connectionStartTime.tv_sec; - if (elapsed < 0 || (static_cast(elapsed) >= g_maxTCPConnectionDuration)) { + if (elapsed < 0 || (static_cast(elapsed) >= currentConfig.d_maxTCPConnectionDuration)) { return now; } - auto remaining = g_maxTCPConnectionDuration - elapsed; + auto remaining = currentConfig.d_maxTCPConnectionDuration - elapsed; if (idleTimeout == 0 || remaining <= static_cast(idleTimeout)) { now.tv_sec += static_cast(remaining); return now; diff --git a/pdns/dnsdistdist/dnsdist-nghttp2.cc b/pdns/dnsdistdist/dnsdist-nghttp2.cc index 68d4f92962e2..ffacf9a19ce4 100644 --- a/pdns/dnsdistdist/dnsdist-nghttp2.cc +++ b/pdns/dnsdistdist/dnsdist-nghttp2.cc @@ -987,7 +987,8 @@ void DoHClientCollection::addThread() { #if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2) try { - auto [sender, receiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, g_tcpInternalPipeBufferSize); + const auto internalPipeBufferSize = dnsdist::configuration::getImmutableConfiguration().d_tcpInternalPipeBufferSize; + auto [sender, receiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, internalPipeBufferSize); vinfolog("Adding DoH Client thread"); std::lock_guard lock(d_mutex); diff --git a/pdns/dnsdistdist/dnsdist-proxy-protocol.cc b/pdns/dnsdistdist/dnsdist-proxy-protocol.cc index d19e87206e2f..01056b1d5a43 100644 --- a/pdns/dnsdistdist/dnsdist-proxy-protocol.cc +++ b/pdns/dnsdistdist/dnsdist-proxy-protocol.cc @@ -21,13 +21,11 @@ */ #include "dnsdist-proxy-protocol.hh" + +#include "dnsdist.hh" #include "dnsdist-metrics.hh" #include "dolog.hh" -NetmaskGroup g_proxyProtocolACL; -size_t g_proxyProtocolMaximumSize = 512; -bool g_applyACLToProxiedClients = false; - std::string getProxyProtocolPayload(const DNSQuestion& dq) { return makeProxyHeader(dq.overTCP(), dq.ids.origRemote, dq.ids.origDest, dq.proxyProtocolValues ? *dq.proxyProtocolValues : std::vector()); @@ -72,7 +70,7 @@ bool addProxyProtocol(PacketBuffer& buffer, bool tcp, const ComboAddress& source bool expectProxyProtocolFrom(const ComboAddress& remote) { - return g_proxyProtocolACL.match(remote); + return dnsdist::configuration::getCurrentRuntimeConfiguration().d_proxyProtocolACL.match(remote); } bool handleProxyProtocol(const ComboAddress& remote, bool isTCP, const NetmaskGroup& acl, PacketBuffer& query, ComboAddress& realRemote, ComboAddress& realDestination, std::vector& values) @@ -86,7 +84,7 @@ bool handleProxyProtocol(const ComboAddress& remote, bool isTCP, const NetmaskGr vinfolog("Ignoring invalid proxy protocol (%d, %d) query over %s from %s", query.size(), used, (isTCP ? "TCP" : "UDP"), remote.toStringWithPort()); return false; } - else if (static_cast(used) > g_proxyProtocolMaximumSize) { + if (static_cast(used) > dnsdist::configuration::getCurrentRuntimeConfiguration().d_proxyProtocolMaximumSize) { vinfolog("Proxy protocol header in %s packet from %s is larger than proxy-protocol-maximum-size (%d), dropping", (isTCP ? "TCP" : "UDP"), remote.toStringWithPort(), used); ++dnsdist::metrics::g_stats.proxyProtocolInvalid; return false; @@ -100,7 +98,7 @@ bool handleProxyProtocol(const ComboAddress& remote, bool isTCP, const NetmaskGr return false; } - if (proxyProto && g_applyACLToProxiedClients) { + if (proxyProto && dnsdist::configuration::getCurrentRuntimeConfiguration().d_applyACLToProxiedClients) { if (!acl.match(realRemote)) { vinfolog("Query from %s dropped because of ACL", realRemote.toStringWithPort()); ++dnsdist::metrics::g_stats.aclDrops; diff --git a/pdns/dnsdistdist/dnsdist-proxy-protocol.hh b/pdns/dnsdistdist/dnsdist-proxy-protocol.hh index de7674a2dbaa..6e4234d6be53 100644 --- a/pdns/dnsdistdist/dnsdist-proxy-protocol.hh +++ b/pdns/dnsdistdist/dnsdist-proxy-protocol.hh @@ -21,11 +21,13 @@ */ #pragma once -#include "dnsdist.hh" +#include -extern NetmaskGroup g_proxyProtocolACL; -extern size_t g_proxyProtocolMaximumSize; -extern bool g_applyACLToProxiedClients; +#include "iputils.hh" +#include "noinitvector.hh" +#include "proxy-protocol.hh" + +struct DNSQuestion; std::string getProxyProtocolPayload(const DNSQuestion& dq); diff --git a/pdns/dnsdistdist/dnsdist-query-count.cc b/pdns/dnsdistdist/dnsdist-query-count.cc new file mode 100644 index 000000000000..8387f28e8dec --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-query-count.cc @@ -0,0 +1,28 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-query-count.hh" + +namespace dnsdist::QueryCount +{ +SharedLockGuarded g_queryCountRecords; +} diff --git a/pdns/dnsdistdist/dnsdist-query-count.hh b/pdns/dnsdistdist/dnsdist-query-count.hh new file mode 100644 index 000000000000..bb9d589cba11 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-query-count.hh @@ -0,0 +1,46 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include +#include +#include +#include + +#include "lock.hh" + +struct DNSQuestion; + +namespace dnsdist::QueryCount +{ +struct Configuration +{ + using Filter = std::function(const DNSQuestion* dq)>; + Configuration() = default; + Filter d_filter; + bool d_enabled{false}; +}; + +using Records = std::unordered_map; +extern SharedLockGuarded g_queryCountRecords; +} diff --git a/pdns/dnsdistdist/dnsdist-secpoll.cc b/pdns/dnsdistdist/dnsdist-secpoll.cc index 26c48ba90194..213b43f43684 100644 --- a/pdns/dnsdistdist/dnsdist-secpoll.cc +++ b/pdns/dnsdistdist/dnsdist-secpoll.cc @@ -91,6 +91,8 @@ static std::string getFirstTXTAnswer(const std::string& answer) static std::string getSecPollStatus(const std::string& queriedName, int timeout=2) { + const auto verbose = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose; + const DNSName sentName(queriedName); std::vector packet; DNSPacketWriter pw(packet, sentName, QType::TXT); @@ -108,13 +110,13 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= string reply; int ret = waitForData(sock.getHandle(), timeout, 0); if (ret < 0) { - if (g_verbose) { + if (verbose) { warnlog("Error while waiting for the secpoll response from stub resolver %s: %d", dest.toString(), ret); } continue; } else if (ret == 0) { - if (g_verbose) { + if (verbose) { warnlog("Timeout while waiting for the secpoll response from stub resolver %s", dest.toString()); } continue; @@ -124,14 +126,14 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= sock.read(reply); } catch(const std::exception& e) { - if (g_verbose) { + if (verbose) { warnlog("Error while reading for the secpoll response from stub resolver %s: %s", dest.toString(), e.what()); } continue; } if (reply.size() <= sizeof(struct dnsheader)) { - if (g_verbose) { + if (verbose) { warnlog("Too short answer of size %d received from the secpoll stub resolver %s", reply.size(), dest.toString()); } continue; @@ -140,14 +142,14 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= struct dnsheader d; memcpy(&d, reply.c_str(), sizeof(d)); if (d.id != pw.getHeader()->id) { - if (g_verbose) { + if (verbose) { warnlog("Invalid ID (%d / %d) received from the secpoll stub resolver %s", d.id, pw.getHeader()->id, dest.toString()); } continue; } if (d.rcode != RCode::NoError) { - if (g_verbose) { + if (verbose) { warnlog("Response code '%s' received from the secpoll stub resolver %s for '%s'", RCode::to_s(d.rcode), dest.toString(), queriedName); } @@ -159,7 +161,7 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= } if (ntohs(d.qdcount) != 1 || ntohs(d.ancount) != 1) { - if (g_verbose) { + if (verbose) { warnlog("Invalid answer (qdcount %d / ancount %d) received from the secpoll stub resolver %s", ntohs(d.qdcount), ntohs(d.ancount), dest.toString()); } continue; @@ -170,7 +172,7 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= DNSName receivedName(reply.c_str(), reply.size(), sizeof(dnsheader), false, &receivedType, &receivedClass); if (receivedName != sentName || receivedType != QType::TXT || receivedClass != QClass::IN) { - if (g_verbose) { + if (verbose) { warnlog("Invalid answer, either the qname (%s / %s), qtype (%s / %s) or qclass (%s / %s) does not match, received from the secpoll stub resolver %s", receivedName, sentName, QType(receivedType).toString(), QType(QType::TXT).toString(), QClass(receivedClass).toString(), QClass::IN.toString(), dest.toString()); } continue; @@ -182,12 +184,12 @@ static std::string getSecPollStatus(const std::string& queriedName, int timeout= throw std::runtime_error("Unable to get a valid Security Status update"); } -static bool g_secPollDone{false}; -std::string g_secPollSuffix{"secpoll.powerdns.com."}; -time_t g_secPollInterval{3600}; - +namespace dnsdist::secpoll +{ void doSecPoll(const std::string& suffix) { + static bool s_secPollDone{false}; + if (suffix.empty()) { return; } @@ -211,7 +213,7 @@ void doSecPoll(const std::string& suffix) int securityStatus = std::stoi(split.first); std::string securityMessage = split.second; - if (securityStatus == 1 && !g_secPollDone) { + if (securityStatus == 1 && !s_secPollDone) { infolog("Polled security status of version %s at startup, no known issues reported: %s", std::string(VERSION), securityMessage); } if (securityStatus == 2) { @@ -222,14 +224,14 @@ void doSecPoll(const std::string& suffix) } dnsdist::metrics::g_stats.securityStatus = securityStatus; - g_secPollDone = true; + s_secPollDone = true; return; } catch (const std::exception& e) { if (releaseVersion) { warnlog("Error while retrieving the security update for version %s: %s", version, e.what()); } - else if (!g_secPollDone) { + else if (!s_secPollDone) { infolog("Error while retrieving the security update for version %s: %s", version, e.what()); } } @@ -237,13 +239,14 @@ void doSecPoll(const std::string& suffix) if (releaseVersion) { warnlog("Failed to retrieve security status update for '%s' on %s", pkgv, queriedName); } - else if (!g_secPollDone) { + else if (!s_secPollDone) { infolog("Not validating response for security status update, this is a non-release version."); /* for non-released versions, there is no use sending the same message several times, let's just accept that there will be no security polling for this exact version */ - g_secPollDone = true; + s_secPollDone = true; } } +} #endif /* DISABLE_SECPOLL */ diff --git a/pdns/dnsdistdist/dnsdist-secpoll.hh b/pdns/dnsdistdist/dnsdist-secpoll.hh index 1a376a8eada1..f2977081edcb 100644 --- a/pdns/dnsdistdist/dnsdist-secpoll.hh +++ b/pdns/dnsdistdist/dnsdist-secpoll.hh @@ -25,10 +25,9 @@ #ifndef DISABLE_SECPOLL #include -#include - -extern std::string g_secPollSuffix; -extern time_t g_secPollInterval; +namespace dnsdist::secpoll +{ void doSecPoll(const std::string& suffix); +} #endif /* DISABLE_SECPOLL */ diff --git a/pdns/dnsdistdist/dnsdist-session-cache.cc b/pdns/dnsdistdist/dnsdist-session-cache.cc index 42ba272ed4b7..de4e6c3639a9 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.cc +++ b/pdns/dnsdistdist/dnsdist-session-cache.cc @@ -21,15 +21,14 @@ */ #include "dnsdist-session-cache.hh" -TLSSessionCache g_sessionCache; +#include "dnsdist-configuration.hh" -time_t TLSSessionCache::s_cleanupDelay{60}; -time_t TLSSessionCache::s_sessionValidity{600}; -uint16_t TLSSessionCache::s_maxSessionsPerBackend{20}; +TLSSessionCache g_sessionCache; void TLSSessionCache::cleanup(time_t now, LockGuardedHolder& data) { - time_t cutOff = now + s_sessionValidity; + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + time_t cutOff = now + runtimeConfig.d_tlsSessionCacheSessionValidity; for (auto it = data->d_sessions.begin(); it != data->d_sessions.end();) { if (it->second.d_lastUsed > cutOff || it->second.d_sessions.size() == 0) { @@ -40,7 +39,7 @@ void TLSSessionCache::cleanup(time_t now, LockGuardedHolderd_nextCleanup = now + s_cleanupDelay; + data->d_nextCleanup = now + runtimeConfig.d_tlsSessionCacheCleanupDelay; } void TLSSessionCache::putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector>&& sessions) @@ -50,9 +49,10 @@ void TLSSessionCache::putSessions(const boost::uuids::uuid& backendID, time_t no cleanup(now, data); } + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); for (auto& session : sessions) { auto& entry = data->d_sessions[backendID]; - if (entry.d_sessions.size() >= s_maxSessionsPerBackend) { + if (entry.d_sessions.size() >= runtimeConfig.d_tlsSessionCacheMaxSessionsPerBackend) { entry.d_sessions.pop_back(); } entry.d_sessions.push_front(std::move(session)); diff --git a/pdns/dnsdistdist/dnsdist-session-cache.hh b/pdns/dnsdistdist/dnsdist-session-cache.hh index 1881fb1af5e5..f4e4cdbaad26 100644 --- a/pdns/dnsdistdist/dnsdist-session-cache.hh +++ b/pdns/dnsdistdist/dnsdist-session-cache.hh @@ -38,28 +38,9 @@ public: void putSessions(const boost::uuids::uuid& backendID, time_t now, std::vector>&& sessions); std::unique_ptr getSession(const boost::uuids::uuid& backendID, time_t now); - static void setCleanupDelay(time_t delay) - { - s_cleanupDelay = delay; - } - - static void setSessionValidity(time_t validity) - { - s_sessionValidity = validity; - } - - static void setMaxTicketsPerBackend(uint16_t max) - { - s_maxSessionsPerBackend = max; - } - size_t getSize(); private: - static time_t s_cleanupDelay; - static time_t s_sessionValidity; - static uint16_t s_maxSessionsPerBackend; - struct BackendEntry { std::deque> d_sessions; diff --git a/pdns/dnsdistdist/dnsdist-snmp.cc b/pdns/dnsdistdist/dnsdist-snmp.cc index ab6a0f2a0902..a1a2cbdd342c 100644 --- a/pdns/dnsdistdist/dnsdist-snmp.cc +++ b/pdns/dnsdistdist/dnsdist-snmp.cc @@ -3,8 +3,6 @@ #include "dnsdist-metrics.hh" #include "dolog.hh" -bool g_snmpEnabled{false}; -bool g_snmpTrapsEnabled{false}; std::unique_ptr g_snmpAgent{nullptr}; #ifdef HAVE_NET_SNMP diff --git a/pdns/dnsdistdist/dnsdist-snmp.hh b/pdns/dnsdistdist/dnsdist-snmp.hh index 7c1deff9b321..13a83bf8695d 100644 --- a/pdns/dnsdistdist/dnsdist-snmp.hh +++ b/pdns/dnsdistdist/dnsdist-snmp.hh @@ -35,3 +35,5 @@ public: bool sendCustomTrap(const std::string& reason); bool sendDNSTrap(const DNSQuestion&, const std::string& reason = ""); }; + +extern std::unique_ptr g_snmpAgent; diff --git a/pdns/dnsdistdist/dnsdist-svc.cc b/pdns/dnsdistdist/dnsdist-svc.cc index 5393f400d63f..d09d8d7bf02f 100644 --- a/pdns/dnsdistdist/dnsdist-svc.cc +++ b/pdns/dnsdistdist/dnsdist-svc.cc @@ -175,9 +175,11 @@ bool generateSVCResponse(DNSQuestion& dnsQuestion, const std::vectortlsFrontend ? d_ci.cs->tlsFrontend->getContext() : (d_ci.cs->dohFrontend ? d_ci.cs->dohFrontend->d_tlsContext.getContext() : nullptr), now.tv_sec), d_connectionStartTime(now), d_ioState(make_unique(*threadData.mplexer, d_ci.fd)), d_threadData(threadData), d_creatorThreadID(std::this_thread::get_id()) + IncomingTCPConnectionState(ConnectionInfo&& ci, TCPClientThreadData& threadData, const struct timeval& now): d_buffer(sizeof(uint16_t)), d_ci(std::move(ci)), d_handler(d_ci.fd, timeval{dnsdist::configuration::getCurrentRuntimeConfiguration().d_tcpRecvTimeout,0}, d_ci.cs->tlsFrontend ? d_ci.cs->tlsFrontend->getContext() : (d_ci.cs->dohFrontend ? d_ci.cs->dohFrontend->d_tlsContext.getContext() : nullptr), now.tv_sec), d_connectionStartTime(now), d_ioState(make_unique(*threadData.mplexer, d_ci.fd)), d_threadData(threadData), d_creatorThreadID(std::this_thread::get_id()) { d_origDest.reset(); d_origDest.sin4.sin_family = d_ci.remote.sin4.sin_family; @@ -57,47 +57,49 @@ public: boost::optional getClientReadTTD(struct timeval now) const { - if (g_maxTCPConnectionDuration == 0 && g_tcpRecvTimeout == 0) { + const auto& runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (runtimeConfiguration.d_maxTCPConnectionDuration == 0 && runtimeConfiguration.d_tcpRecvTimeout == 0) { return boost::none; } - if (g_maxTCPConnectionDuration > 0) { + if (runtimeConfiguration.d_maxTCPConnectionDuration > 0) { auto elapsed = now.tv_sec - d_connectionStartTime.tv_sec; - if (elapsed < 0 || (static_cast(elapsed) >= g_maxTCPConnectionDuration)) { + if (elapsed < 0 || (static_cast(elapsed) >= runtimeConfiguration.d_maxTCPConnectionDuration)) { return now; } - auto remaining = g_maxTCPConnectionDuration - elapsed; - if (g_tcpRecvTimeout == 0 || remaining <= static_cast(g_tcpRecvTimeout)) { + auto remaining = runtimeConfiguration.d_maxTCPConnectionDuration - elapsed; + if (runtimeConfiguration.d_tcpRecvTimeout == 0 || remaining <= static_cast(runtimeConfiguration.d_tcpRecvTimeout)) { now.tv_sec += remaining; return now; } } - now.tv_sec += g_tcpRecvTimeout; + now.tv_sec += runtimeConfiguration.d_tcpRecvTimeout; return now; } boost::optional getClientWriteTTD(const struct timeval& now) const { - if (g_maxTCPConnectionDuration == 0 && g_tcpSendTimeout == 0) { + const auto& runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (runtimeConfiguration.d_maxTCPConnectionDuration == 0 && runtimeConfiguration.d_tcpSendTimeout == 0) { return boost::none; } - struct timeval res = now; + timeval res(now); - if (g_maxTCPConnectionDuration > 0) { + if (runtimeConfiguration.d_maxTCPConnectionDuration > 0) { auto elapsed = res.tv_sec - d_connectionStartTime.tv_sec; - if (elapsed < 0 || static_cast(elapsed) >= g_maxTCPConnectionDuration) { + if (elapsed < 0 || static_cast(elapsed) >= runtimeConfiguration.d_maxTCPConnectionDuration) { return res; } - auto remaining = g_maxTCPConnectionDuration - elapsed; - if (g_tcpSendTimeout == 0 || remaining <= static_cast(g_tcpSendTimeout)) { + auto remaining = runtimeConfiguration.d_maxTCPConnectionDuration - elapsed; + if (runtimeConfiguration.d_tcpSendTimeout == 0 || remaining <= static_cast(runtimeConfiguration.d_tcpSendTimeout)) { res.tv_sec += remaining; return res; } } - res.tv_sec += g_tcpSendTimeout; + res.tv_sec += runtimeConfiguration.d_tcpSendTimeout; return res; } diff --git a/pdns/dnsdistdist/dnsdist-tcp.cc b/pdns/dnsdistdist/dnsdist-tcp.cc index b7ca45a6f9c2..09be1441d246 100644 --- a/pdns/dnsdistdist/dnsdist-tcp.cc +++ b/pdns/dnsdistdist/dnsdist-tcp.cc @@ -60,25 +60,9 @@ Let's start naively. */ -size_t g_maxTCPQueriesPerConn{0}; -size_t g_maxTCPConnectionDuration{0}; - -#ifdef __linux__ -// On Linux this gives us 128k pending queries (default is 8192 queries), -// which should be enough to deal with huge spikes -size_t g_tcpInternalPipeBufferSize{1048576U}; -uint64_t g_maxTCPQueuedConnections{10000}; -#else -size_t g_tcpInternalPipeBufferSize{0}; -uint64_t g_maxTCPQueuedConnections{1000}; -#endif - -int g_tcpRecvTimeout{2}; -int g_tcpSendTimeout{2}; std::atomic g_tcpStatesDumpRequested{0}; LockGuarded> dnsdist::IncomingConcurrentTCPConnectionsManager::s_tcpClientsConcurrentConnectionsCount; -size_t dnsdist::IncomingConcurrentTCPConnectionsManager::s_maxTCPConnectionsPerClient = 0; IncomingTCPConnectionState::~IncomingTCPConnectionState() { @@ -142,11 +126,13 @@ TCPClientCollection::TCPClientCollection(size_t maxThreads, std::vector& tcpAcceptStates) { try { - auto [queryChannelSender, queryChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, g_tcpInternalPipeBufferSize); + const auto internalPipeBufferSize = dnsdist::configuration::getImmutableConfiguration().d_tcpInternalPipeBufferSize; + + auto [queryChannelSender, queryChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, internalPipeBufferSize); - auto [crossProtocolQueryChannelSender, crossProtocolQueryChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, g_tcpInternalPipeBufferSize); + auto [crossProtocolQueryChannelSender, crossProtocolQueryChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, internalPipeBufferSize); - auto [crossProtocolResponseChannelSender, crossProtocolResponseChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, g_tcpInternalPipeBufferSize); + auto [crossProtocolResponseChannelSender, crossProtocolResponseChannelReceiver] = pdns::channel::createObjectQueue(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, internalPipeBufferSize); vinfolog("Adding TCP Client thread"); @@ -251,12 +237,13 @@ bool IncomingTCPConnectionState::canAcceptNewQueries(const struct timeval& now) return false; } - if (g_maxTCPQueriesPerConn != 0 && d_queriesCount > g_maxTCPQueriesPerConn) { - vinfolog("not accepting new queries from %s because it reached the maximum number of queries per conn (%d / %d)", d_ci.remote.toStringWithPort(), d_queriesCount, g_maxTCPQueriesPerConn); + const auto& currentConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (currentConfig.d_maxTCPQueriesPerConn != 0 && d_queriesCount > currentConfig.d_maxTCPQueriesPerConn) { + vinfolog("not accepting new queries from %s because it reached the maximum number of queries per conn (%d / %d)", d_ci.remote.toStringWithPort(), d_queriesCount, currentConfig.d_maxTCPQueriesPerConn); return false; } - if (maxConnectionDurationReached(g_maxTCPConnectionDuration, now)) { + if (maxConnectionDurationReached(currentConfig.d_maxTCPConnectionDuration, now)) { vinfolog("not accepting new queries from %s because it reached the maximum TCP connection duration", d_ci.remote.toStringWithPort()); return false; } @@ -498,11 +485,12 @@ void IncomingTCPConnectionState::handleResponse(const struct timeval& now, TCPRe return; } + const auto config = dnsdist::configuration::getCurrentRuntimeConfiguration(); if (!response.isAsync()) { try { auto& ids = response.d_idstate; std::shared_ptr backend = response.d_ds ? response.d_ds : (response.d_connection ? response.d_connection->getDS() : nullptr); - if (backend == nullptr || !responseContentMatches(response.d_buffer, ids.qname, ids.qtype, ids.qclass, backend)) { + if (backend == nullptr || !responseContentMatches(response.d_buffer, ids.qname, ids.qtype, ids.qclass, backend, config.d_allowEmptyResponse)) { state->terminateClientConnection(); return; } @@ -1068,7 +1056,8 @@ void IncomingTCPConnectionState::handleIO() iostate = IOState::Done; IOStateGuard ioGuard(d_ioState); - if (maxConnectionDurationReached(g_maxTCPConnectionDuration, now)) { + const auto& currentConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (maxConnectionDurationReached(currentConfig.d_maxTCPConnectionDuration, now)) { vinfolog("Terminating TCP connection from %s because it reached the maximum TCP connection duration", d_ci.remote.toStringWithPort()); // will be handled by the ioGuard // handleNewIOState(state, IOState::Done, fd, handleIOCallback); @@ -1608,7 +1597,8 @@ static void acceptNewConnection(const TCPAcceptorParam& param, TCPClientThreadDa setTCPNoDelay(connInfo.fd); // disable NAGLE - if (g_maxTCPQueuedConnections > 0 && g_tcpclientthreads->getQueuedCount() >= g_maxTCPQueuedConnections) { + const auto maxTCPQueuedConnections = dnsdist::configuration::getImmutableConfiguration().d_maxTCPQueuedConnections; + if (maxTCPQueuedConnections > 0 && g_tcpclientthreads->getQueuedCount() >= maxTCPQueuedConnections) { vinfolog("Dropping TCP connection from %s because we have too many queued already", remote.toStringWithPort()); return; } diff --git a/pdns/dnsdistdist/dnsdist-web.cc b/pdns/dnsdistdist/dnsdist-web.cc index 368ee9e75a63..24395fdb0a03 100644 --- a/pdns/dnsdistdist/dnsdist-web.cc +++ b/pdns/dnsdistdist/dnsdist-web.cc @@ -32,6 +32,7 @@ #include "base64.hh" #include "connection-management.hh" #include "dnsdist.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-dynblocks.hh" #include "dnsdist-healthchecks.hh" #include "dnsdist-metrics.hh" @@ -60,9 +61,7 @@ struct WebserverConfig bool statsRequireAuthentication{true}; }; -bool g_apiReadWrite{false}; LockGuarded g_webserverConfig; -std::string g_apiConfigDirectory; static ConcurrentConnectionManager s_connManager(100); @@ -90,9 +89,12 @@ std::string getWebserverConfig() out << "Password: " << (config->password ? "set" : "unset") << endl; out << "API key: " << (config->apiKey ? "set" : "unset") << endl; } - out << "API writable: " << (g_apiReadWrite ? "yes" : "no") << endl; - out << "API configuration directory: " << g_apiConfigDirectory << endl; - out << "Maximum concurrent connections: " << s_connManager.getMaxConcurrentConnections() << endl; + { + const auto& config = dnsdist::configuration::getCurrentRuntimeConfiguration(); + out << "API writable: " << (config.d_apiReadWrite ? "yes" : "no") << endl; + out << "API configuration directory: " << config.d_apiConfigDirectory << endl; + out << "Maximum concurrent connections: " << s_connManager.getMaxConcurrentConnections() << endl; + } return out.str(); } @@ -238,17 +240,18 @@ bool addMetricDefinition(const dnsdist::prometheus::PrometheusMetricDefinition& #ifndef DISABLE_WEB_CONFIG static bool apiWriteConfigFile(const string& filebasename, const string& content) { - if (!g_apiReadWrite) { + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (!runtimeConfig.d_apiReadWrite) { warnlog("Not writing content to %s since the API is read-only", filebasename); return false; } - if (g_apiConfigDirectory.empty()) { + if (runtimeConfig.d_apiConfigDirectory.empty()) { vinfolog("Not writing content to %s since the API configuration directory is not set", filebasename); return false; } - string filename = g_apiConfigDirectory + "/" + filebasename + ".conf"; + string filename = runtimeConfig.d_apiConfigDirectory + "/" + filebasename + ".conf"; ofstream ofconf(filename.c_str()); if (!ofconf) { errlog("Could not open configuration fragment file '%s' for writing: %s", filename, stringerror()); @@ -365,7 +368,7 @@ static bool isMethodAllowed(const YaHTTP::Request& req) if (req.method == "GET") { return true; } - if (req.method == "PUT" && g_apiReadWrite) { + if (req.method == "PUT" && dnsdist::configuration::getCurrentRuntimeConfiguration().d_apiReadWrite) { if (req.url.path == "/api/v1/servers/localhost/config/allow-from") { return true; } @@ -391,7 +394,7 @@ static void handleCORS(const YaHTTP::Request& req, YaHTTP::Response& resp) if (origin != req.headers.end()) { if (req.method == "OPTIONS") { /* Pre-flight request */ - if (g_apiReadWrite) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_apiReadWrite) { resp.headers["Access-Control-Allow-Methods"] = "GET, PUT"; } else { @@ -969,6 +972,7 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) } const string& command = req.getvars.at("command"); + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); if (command == "stats") { auto obj = Json::object{ @@ -1002,14 +1006,14 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"reason", entry.second.reason}, {"seconds", static_cast(entry.second.until.tv_sec - now.tv_sec)}, {"blocks", static_cast(counter)}, - {"action", DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : g_dynBlockAction)}, + {"action", DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : runtimeConfig.d_dynBlockAction)}, {"warning", entry.second.warning}, {"ebpf", entry.second.bpf}}; obj.emplace(entry.first.toString(), thing); } auto smt = g_dynblockSMT.getLocal(); - smt->visit([&now, &obj](const SuffixMatchTree& node) { + smt->visit([&now, &obj, &runtimeConfig](const SuffixMatchTree& node) { if (!(now < node.d_value.until)) { return; } @@ -1021,7 +1025,7 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"reason", node.d_value.reason}, {"seconds", static_cast(node.d_value.until.tv_sec - now.tv_sec)}, {"blocks", static_cast(node.d_value.blocks)}, - {"action", DNSAction::typeToString(node.d_value.action != DNSAction::Action::None ? node.d_value.action : g_dynBlockAction)}, + {"action", DNSAction::typeToString(node.d_value.action != DNSAction::Action::None ? node.d_value.action : runtimeConfig.d_dynBlockAction)}, {"ebpf", node.d_value.bpf}}; obj.emplace(dom, thing); }); @@ -1055,7 +1059,7 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"reason", entry.second.reason}, {"seconds", static_cast(entry.second.until.tv_sec - now.tv_sec)}, {"blocks", static_cast(counter)}, - {"action", DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : g_dynBlockAction)}, + {"action", DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : runtimeConfig.d_dynBlockAction)}, {"warning", entry.second.warning}, }; obj.emplace(entry.first.toString(), thing); @@ -1442,23 +1446,25 @@ static void handleConfigDump(const YaHTTP::Request& req, YaHTTP::Response& resp) resp.status = 200; Json::array doc; - typedef boost::variant configentry_t; + const auto runtimeConfiguration = dnsdist::configuration::getCurrentRuntimeConfiguration(); + const auto immutableConfig = dnsdist::configuration::getImmutableConfiguration(); + using configentry_t = boost::variant; std::vector> configEntries{ {"acl", g_ACL.getLocal()->toString()}, - {"allow-empty-response", g_allowEmptyResponse}, + {"allow-empty-response", runtimeConfiguration.d_allowEmptyResponse}, {"control-socket", g_serverControl.toStringWithPort()}, - {"ecs-override", g_ECSOverride}, - {"ecs-source-prefix-v4", (double)g_ECSSourcePrefixV4}, - {"ecs-source-prefix-v6", (double)g_ECSSourcePrefixV6}, - {"fixup-case", g_fixupCase}, - {"max-outstanding", (double)g_maxOutstanding}, + {"ecs-override", runtimeConfiguration.d_ecsOverride}, + {"ecs-source-prefix-v4", static_cast(runtimeConfiguration.d_ECSSourcePrefixV4)}, + {"ecs-source-prefix-v6", static_cast(runtimeConfiguration.d_ECSSourcePrefixV6)}, + {"fixup-case", runtimeConfiguration.d_fixupCase}, + {"max-outstanding", static_cast(immutableConfig.d_maxUDPOutstanding)}, {"server-policy", g_policy.getLocal()->getName()}, - {"stale-cache-entries-ttl", (double)g_staleCacheEntriesTTL}, - {"tcp-recv-timeout", (double)g_tcpRecvTimeout}, - {"tcp-send-timeout", (double)g_tcpSendTimeout}, - {"truncate-tc", g_truncateTC}, - {"verbose", g_verbose}, - {"verbose-health-checks", g_verboseHealthChecks}}; + {"stale-cache-entries-ttl", static_cast(runtimeConfiguration.d_staleCacheEntriesTTL)}, + {"tcp-recv-timeout", static_cast(runtimeConfiguration.d_tcpRecvTimeout)}, + {"tcp-send-timeout", static_cast(runtimeConfiguration.d_tcpSendTimeout)}, + {"truncate-tc", runtimeConfiguration.d_truncateTC}, + {"verbose", runtimeConfiguration.d_verbose}, + {"verbose-health-checks", runtimeConfiguration.d_verboseHealthChecks}}; for (const auto& item : configEntries) { if (const auto& bval = boost::get(&item.second)) { doc.emplace_back(Json::object{ diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 4fd2dc499b03..87d13d179cdb 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -52,6 +52,7 @@ #include "dnsdist-async.hh" #include "dnsdist-cache.hh" #include "dnsdist-carbon.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-console.hh" #include "dnsdist-crypto.hh" #include "dnsdist-discovery.hh" @@ -67,6 +68,7 @@ #include "dnsdist-random.hh" #include "dnsdist-rings.hh" #include "dnsdist-secpoll.hh" +#include "dnsdist-snmp.hh" #include "dnsdist-tcp.hh" #include "dnsdist-web.hh" #include "dnsdist-xsk.hh" @@ -100,11 +102,6 @@ on the Lua side we can't do that. */ using std::thread; -bool g_verbose; - -uint16_t g_maxOutstanding{std::numeric_limits::max()}; -uint32_t g_staleCacheEntriesTTL{0}; -bool g_allowEmptyResponse{false}; GlobalStateHolder g_ACL; string g_outputBuffer; @@ -120,7 +117,6 @@ std::vector> g_dynBPFFilters; std::vector> g_frontends; GlobalStateHolder g_pools; -size_t g_udpVectorSize{1}; std::vector g_TCPFastOpenKey; /* UDP: the grand design. Per socket we listen on for incoming queries there is one thread. Then we have a bunch of connected sockets for talking to downstream servers. @@ -138,17 +134,9 @@ std::vector g_TCPFastOpenKey; */ Rings g_rings; -QueryCount g_qcount; GlobalStateHolder g_dstates; -bool g_servFailOnNoPolicy{false}; -bool g_truncateTC{false}; -bool g_fixupCase{false}; -bool g_dropEmptyQueries{false}; -uint32_t g_socketUDPSendBuffer{0}; -uint32_t g_socketUDPRecvBuffer{0}; - std::set g_capabilitiesToRetain; // we are not willing to receive a bigger UDP response than that, no matter what @@ -177,14 +165,14 @@ static void sendfromto(int sock, const PacketBuffer& buffer, const ComboAddress& } } -static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qnameWireLength) +static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qnameWireLength, bool addEDNSToSelfGeneratedResponses) { try { bool hadEDNS = false; uint16_t payloadSize = 0; uint16_t zValue = 0; - if (g_addEDNSToSelfGeneratedResponses) { + if (addEDNSToSelfGeneratedResponses) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) hadEDNS = getEDNSUDPPayloadSizeAndZ(reinterpret_cast(packet.data()), packet.size(), &payloadSize, &zValue); } @@ -320,7 +308,7 @@ static void doLatencyStats(dnsdist::Protocol protocol, double udiff) } } -bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote) +bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote, bool allowEmptyResponse) { if (response.size() < sizeof(dnsheader)) { return false; @@ -336,7 +324,7 @@ bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, } if (dnsHeader->qdcount == 0) { - if ((dnsHeader->rcode != RCode::NoError && dnsHeader->rcode != RCode::NXDomain) || g_allowEmptyResponse) { + if ((dnsHeader->rcode != RCode::NoError && dnsHeader->rcode != RCode::NXDomain) || allowEmptyResponse) { return true; } @@ -407,7 +395,7 @@ static bool fixUpResponse(PacketBuffer& response, const DNSName& qname, uint16_t return true; } - if (g_fixupCase) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_fixupCase) { const auto& realname = qname.getStorage(); if (response.size() >= (sizeof(dnsheader) + realname.length())) { memcpy(&response.at(sizeof(dnsheader)), realname.c_str(), realname.length()); @@ -532,7 +520,7 @@ bool applyRulesToResponse(const std::vector& header.qr = true; return true; }); - truncateTC(dnsResponse.getMutableData(), dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength()); + truncateTC(dnsResponse.getMutableData(), dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength(), dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses); ++dnsdist::metrics::g_stats.ruleTruncated; return true; } @@ -621,13 +609,14 @@ bool processResponse(PacketBuffer& response, const std::vector 0 && response.size() > ids.udpPayloadSize) { vinfolog("Got a response of size %d while the initial UDP payload size was %d, truncating", response.size(), ids.udpPayloadSize); - truncateTC(dnsResponse.getMutableData(), dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength()); + truncateTC(dnsResponse.getMutableData(), dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength(), dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses); dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsResponse.getMutableData(), [](dnsheader& header) { header.tc = true; return true; }); } - else if (dnsResponse.getHeader()->tc && g_truncateTC) { - truncateTC(response, dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength()); + else if (dnsResponse.getHeader()->tc && dnsdist::configuration::getCurrentRuntimeConfiguration().d_truncateTC) { + truncateTC(response, dnsResponse.getMaximumSize(), dnsResponse.ids.qname.wirelength(), dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses); } /* when the answer is encrypted in place, we need to get a copy @@ -757,7 +747,7 @@ bool processResponderPacket(std::shared_ptr& dss, PacketBuffer& const dnsheader_aligned dnsHeader(response.data()); auto queryId = dnsHeader->id; - if (!responseContentMatches(response, ids.qname, ids.qtype, ids.qclass, dss)) { + if (!responseContentMatches(response, ids.qname, ids.qtype, ids.qclass, dss, dnsdist::configuration::getCurrentRuntimeConfiguration().d_allowEmptyResponse)) { dss->restoreState(queryId, std::move(ids)); return false; } @@ -1060,16 +1050,17 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dnsQuestion, c g_rings.insertQuery(now, dnsQuestion.ids.origRemote, dnsQuestion.ids.qname, dnsQuestion.ids.qtype, dnsQuestion.getData().size(), *dnsQuestion.getHeader(), dnsQuestion.getProtocol()); } - if (g_qcount.enabled) { + const auto runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + if (runtimeConfig.d_queryCountConfig.d_enabled) { string qname = dnsQuestion.ids.qname.toLogString(); bool countQuery{true}; - if (g_qcount.filter) { + if (runtimeConfig.d_queryCountConfig.d_filter) { auto lock = g_lua.lock(); - std::tie(countQuery, qname) = g_qcount.filter(&dnsQuestion); + std::tie(countQuery, qname) = runtimeConfig.d_queryCountConfig.d_filter(&dnsQuestion); } if (countQuery) { - auto records = g_qcount.records.write_lock(); + auto records = dnsdist::QueryCount::g_queryCountRecords.write_lock(); if (records->count(qname) == 0) { (*records)[qname] = 0; } @@ -1096,7 +1087,7 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dnsQuestion, c if (now < got->second.until) { DNSAction::Action action = got->second.action; if (action == DNSAction::Action::None) { - action = g_dynBlockAction; + action = runtimeConfig.d_dynBlockAction; } switch (action) { @@ -1173,7 +1164,7 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dnsQuestion, c if (now < got->until) { DNSAction::Action action = got->action; if (action == DNSAction::Action::None) { - action = g_dynBlockAction; + action = runtimeConfig.d_dynBlockAction; } switch (action) { case DNSAction::Action::NoOp: @@ -1356,7 +1347,7 @@ bool checkQueryHeaders(const struct dnsheader& dnsHeader, ClientState& clientSta if (dnsHeader.qdcount == 0) { ++dnsdist::metrics::g_stats.emptyQueries; - if (g_dropEmptyQueries) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_dropEmptyQueries) { return false; } } @@ -1475,7 +1466,7 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dnsQuestion, LocalHolders dnsQuestion.ids.packetCache = serverPool->packetCache; selectBackendForOutgoingQuery(dnsQuestion, serverPool, holders, selectedBackend); - uint32_t allowExpired = selectedBackend ? 0 : g_staleCacheEntriesTTL; + uint32_t allowExpired = selectedBackend ? 0 : dnsdist::configuration::getCurrentRuntimeConfiguration().d_staleCacheEntriesTTL; if (dnsQuestion.ids.packetCache && !dnsQuestion.ids.skipCache) { dnsQuestion.ids.dnssecOK = (getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO) != 0; @@ -1570,10 +1561,11 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dnsQuestion, LocalHolders } if (!selectedBackend) { + auto servFailOnNoPolicy = dnsdist::configuration::getCurrentRuntimeConfiguration().d_servFailOnNoPolicy; ++dnsdist::metrics::g_stats.noPolicy; - vinfolog("%s query for %s|%s from %s, no downstream server available", g_servFailOnNoPolicy ? "ServFailed" : "Dropped", dnsQuestion.ids.qname.toLogString(), QType(dnsQuestion.ids.qtype).toString(), dnsQuestion.ids.origRemote.toStringWithPort()); - if (g_servFailOnNoPolicy) { + vinfolog("%s query for %s|%s from %s, no downstream server available", servFailOnNoPolicy ? "ServFailed" : "Dropped", dnsQuestion.ids.qname.toLogString(), QType(dnsQuestion.ids.qtype).toString(), dnsQuestion.ids.origRemote.toStringWithPort()); + if (servFailOnNoPolicy) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [](dnsheader& header) { header.rcode = RCode::ServFail; header.qr = true; @@ -2070,7 +2062,7 @@ static void MultipleMessagesUDPClientThread(ClientState* clientState, LocalHolde /* used by HarvestDestinationAddress */ cmsgbuf_aligned cbuf{}; }; - const size_t vectSize = g_udpVectorSize; + const size_t vectSize = dnsdist::configuration::getImmutableConfiguration().d_udpVectorSize; if (vectSize > std::numeric_limits::max()) { throw std::runtime_error("The value of setUDPMultipleMessagesVectorSize is too high, the maximum value is " + std::to_string(std::numeric_limits::max())); @@ -2157,7 +2149,7 @@ static void udpClientThread(std::vector states) LocalHolders holders; #ifndef DISABLE_RECVMMSG #if defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE) - if (g_udpVectorSize > 1) { + if (dnsdist::configuration::getImmutableConfiguration().d_udpVectorSize > 1) { MultipleMessagesUDPClientThread(states.at(0), holders); } else @@ -2268,10 +2260,6 @@ static void udpClientThread(std::vector states) } } -boost::optional g_maxTCPClientThreads{boost::none}; -pdns::stat16_t g_cacheCleaningDelay{60}; -pdns::stat16_t g_cacheCleaningPercentage{100}; - static void maintThread() { setThreadName("dnsdist/main"); @@ -2281,6 +2269,7 @@ static void maintThread() for (;;) { std::this_thread::sleep_for(std::chrono::seconds(interval)); + const auto& config = dnsdist::configuration::getCurrentRuntimeConfiguration(); { auto lua = g_lua.lock(); @@ -2302,7 +2291,7 @@ static void maintThread() } counter++; - if (counter >= g_cacheCleaningDelay) { + if (counter >= config.d_cacheCleaningDelay) { /* keep track, for each cache, of whether we should keep expired entries */ std::map, bool> caches; @@ -2338,7 +2327,7 @@ static void maintThread() continue; } const auto& packetCache = pair.first; - size_t upTo = (packetCache->getMaxEntries() * (100 - g_cacheCleaningPercentage)) / 100; + size_t upTo = (packetCache->getMaxEntries() * (100 - config.d_cacheCleaningPercentage)) / 100; packetCache->purgeExpired(upTo, now); } counter = 0; @@ -2361,13 +2350,15 @@ static void secPollThread() setThreadName("dnsdist/secpoll"); for (;;) { + const auto& runtimeConfig = dnsdist::configuration::getCurrentRuntimeConfiguration(); + try { - doSecPoll(g_secPollSuffix); + dnsdist::secpoll::doSecPoll(runtimeConfig.d_secPollSuffix); } catch (...) { } // coverity[store_truncates_time_t] - std::this_thread::sleep_for(std::chrono::seconds(g_secPollInterval)); + std::this_thread::sleep_for(std::chrono::seconds(runtimeConfig.d_secPollInterval)); } } #endif /* DISABLE_SECPOLL */ @@ -2477,6 +2468,7 @@ static void dropUserPrivs(uid_t uid) static void checkFileDescriptorsLimits(size_t udpBindsCount, size_t tcpBindsCount) { + const auto immutableConfig = dnsdist::configuration::getImmutableConfiguration(); /* stdin, stdout, stderr */ rlim_t requiredFDsCount = 3; auto backends = g_dstates.getLocal(); @@ -2487,20 +2479,20 @@ static void checkFileDescriptorsLimits(size_t udpBindsCount, size_t tcpBindsCoun } requiredFDsCount += backendUDPSocketsCount; /* TCP sockets to backends */ - if (g_maxTCPClientThreads) { - requiredFDsCount += (backends->size() * (*g_maxTCPClientThreads)); + if (immutableConfig.d_maxTCPClientThreads > 0) { + requiredFDsCount += (backends->size() * immutableConfig.d_maxTCPClientThreads); } /* listening sockets */ requiredFDsCount += udpBindsCount; requiredFDsCount += tcpBindsCount; /* number of TCP connections currently served, assuming 1 connection per worker thread which is of course not right */ - if (g_maxTCPClientThreads) { - requiredFDsCount += *g_maxTCPClientThreads; + if (immutableConfig.d_maxTCPClientThreads > 0) { + requiredFDsCount += immutableConfig.d_maxTCPClientThreads; /* max pipes for communicating between TCP acceptors and client threads */ - requiredFDsCount += (*g_maxTCPClientThreads * 2); + requiredFDsCount += (immutableConfig.d_maxTCPClientThreads * 2); } /* max TCP queued connections */ - requiredFDsCount += g_maxTCPQueuedConnections; + requiredFDsCount += immutableConfig.d_maxTCPQueuedConnections; /* DelayPipe pipe */ requiredFDsCount += 2; /* syslog socket */ @@ -2525,10 +2517,10 @@ static void checkFileDescriptorsLimits(size_t udpBindsCount, size_t tcpBindsCoun } } -static bool g_warned_ipv6_recvpktinfo = false; - static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, int& socket, bool tcp, bool warn) { + const auto immutableConfig = dnsdist::configuration::getImmutableConfiguration(); + static bool s_warned_ipv6_recvpktinfo = false; (void)warn; socket = SSocket(addr.sin4.sin_family, !tcp ? SOCK_DGRAM : SOCK_STREAM, 0); @@ -2566,9 +2558,9 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, int one = 1; (void)setsockopt(socket, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems #ifdef IPV6_RECVPKTINFO - if (addr.isIPv6() && setsockopt(socket, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)) < 0 && !g_warned_ipv6_recvpktinfo) { + if (addr.isIPv6() && setsockopt(socket, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one)) < 0 && !s_warned_ipv6_recvpktinfo) { warnlog("Warning: IPV6_RECVPKTINFO setsockopt failed: %s", stringerror()); - g_warned_ipv6_recvpktinfo = true; + s_warned_ipv6_recvpktinfo = true; } #endif } @@ -2605,9 +2597,9 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, } if (!tcp) { - if (g_socketUDPSendBuffer > 0) { + if (immutableConfig.d_socketUDPSendBuffer > 0) { try { - setSocketSendBuffer(socket, g_socketUDPSendBuffer); + setSocketSendBuffer(socket, immutableConfig.d_socketUDPSendBuffer); } catch (const std::exception& e) { warnlog(e.what()); @@ -2625,9 +2617,9 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, } } - if (g_socketUDPRecvBuffer > 0) { + if (immutableConfig.d_socketUDPRecvBuffer > 0) { try { - setSocketReceiveBuffer(socket, g_socketUDPRecvBuffer); + setSocketReceiveBuffer(socket, immutableConfig.d_socketUDPRecvBuffer); } catch (const std::exception& e) { warnlog(e.what()); @@ -2962,6 +2954,8 @@ static void parseParameters(int argc, char** argv, ComboAddress& clientAddress) {nullptr, 0, nullptr, 0}}}; int longindex = 0; string optstring; + dnsdist::configuration::RuntimeConfiguration newConfig; + while (true) { // NOLINTNEXTLINE(concurrency-mt-unsafe): only one thread at this point int gotChar = getopt_long(argc, argv, "a:cC:e:g:hk:l:u:vV", longopts.data(), &longindex); @@ -3006,17 +3000,23 @@ static void parseParameters(int argc, char** argv, ComboAddress& clientAddress) break; case 'k': #if defined HAVE_LIBSODIUM || defined(HAVE_LIBCRYPTO) - if (B64Decode(string(optarg), g_consoleKey) < 0) { + { + std::string consoleKey; + if (B64Decode(string(optarg), consoleKey) < 0) { cerr << "Unable to decode key '" << optarg << "'." << endl; // NOLINTNEXTLINE(concurrency-mt-unsafe): only one thread at this point exit(EXIT_FAILURE); } + dnsdist::configuration::updateImmutableConfiguration([&consoleKey](dnsdist::configuration::Configuration& config) { + config.d_consoleKey = std::move(consoleKey); + }); + } #else cerr << "dnsdist has been built without libsodium or libcrypto, -k/--setkey is unsupported." << endl; // NOLINTNEXTLINE(concurrency-mt-unsafe): only one thread at this point exit(EXIT_FAILURE); #endif - break; + break; case 'l': g_cmdLine.locals.push_back(boost::trim_copy(string(optarg))); break; @@ -3024,7 +3024,7 @@ static void parseParameters(int argc, char** argv, ComboAddress& clientAddress) g_cmdLine.uid = optarg; break; case 'v': - g_verbose = true; + newConfig.d_verbose = true; break; case 'V': reportFeatures(); @@ -3052,6 +3052,10 @@ static void parseParameters(int argc, char** argv, ComboAddress& clientAddress) g_cmdLine.remotes.emplace_back(*ptr); } } + + dnsdist::configuration::updateRuntimeConfiguration([&newConfig](dnsdist::configuration::RuntimeConfiguration& config) { + config = std::move(newConfig); + }); } static void setupPools() { @@ -3286,7 +3290,9 @@ int main(int argc, char** argv) } #endif dnsdist::initRandom(); - g_hashperturb = dnsdist::getRandomValue(0xffffffff); + dnsdist::configuration::updateImmutableConfiguration([](dnsdist::configuration::Configuration& config) { + config.d_hashPerturbation = dnsdist::getRandomValue(0xffffffff); + }); #ifdef HAVE_XSK try { @@ -3327,11 +3333,12 @@ int main(int argc, char** argv) g_ACL.setState(acl); } - auto consoleACL = g_consoleACL.getCopy(); - for (const auto& mask : {"127.0.0.1/8", "::1/128"}) { - consoleACL.addMask(mask); - } - g_consoleACL.setState(consoleACL); + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + for (const auto& mask : {"127.0.0.1/8", "::1/128"}) { + config.d_consoleACL.addMask(mask); + } + }); + registerBuiltInWebHandlers(); if (g_cmdLine.checkConfig) { @@ -3356,13 +3363,7 @@ int main(int argc, char** argv) initFrontends(); - g_configurationDone = true; - - g_rings.init(); - - for (auto& frontend : g_frontends) { - setUpLocalBind(frontend); - + for (const auto& frontend : g_frontends) { if (!frontend->tcp) { ++udpBindsCount; } @@ -3371,6 +3372,20 @@ int main(int argc, char** argv) } } + if (dnsdist::configuration::getImmutableConfiguration().d_maxTCPClientThreads == 0 && tcpBindsCount > 0) { + dnsdist::configuration::updateImmutableConfiguration([](dnsdist::configuration::Configuration& config) { + config.d_maxTCPClientThreads = static_cast(10); + }); + } + + g_configurationDone = true; + + g_rings.init(); + + for (auto& frontend : g_frontends) { + setUpLocalBind(frontend); + } + { std::string acls; auto aclEntries = g_ACL.getLocal()->toStringVector(); @@ -3384,7 +3399,7 @@ int main(int argc, char** argv) } { std::string acls; - auto aclEntries = g_consoleACL.getLocal()->toStringVector(); + auto aclEntries = dnsdist::configuration::getCurrentRuntimeConfiguration().d_consoleACL.toStringVector(); for (const auto& entry : aclEntries) { if (!acls.empty()) { acls += ", "; @@ -3395,7 +3410,7 @@ int main(int argc, char** argv) } #if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO) - if (g_consoleEnabled && g_consoleKey.empty()) { + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_consoleEnabled && dnsdist::configuration::getImmutableConfiguration().d_consoleKey.empty()) { warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set"); } #endif @@ -3411,19 +3426,11 @@ int main(int argc, char** argv) g_snmpAgent->run(); } - if (!g_maxTCPClientThreads) { - g_maxTCPClientThreads = static_cast(10); - } - else if (*g_maxTCPClientThreads == 0 && tcpBindsCount > 0) { - warnlog("setMaxTCPClientThreads() has been set to 0 while we are accepting TCP connections, raising to 1"); - g_maxTCPClientThreads = 1; - } - /* we need to create the TCP worker threads before the acceptor ones, otherwise we might crash when processing the first TCP query */ #ifndef USE_SINGLE_ACCEPTOR_THREAD - g_tcpclientthreads = std::make_unique(*g_maxTCPClientThreads, std::vector()); + g_tcpclientthreads = std::make_unique(dnsdist::configuration::getImmutableConfiguration().d_maxTCPClientThreads, std::vector()); #endif #if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2) @@ -3495,7 +3502,7 @@ int main(int argc, char** argv) #endif /* DISABLE_DYNBLOCKS */ #ifndef DISABLE_SECPOLL - if (!g_secPollSuffix.empty()) { + if (!dnsdist::configuration::getCurrentRuntimeConfiguration().d_secPollSuffix.empty()) { thread secpollthread(secPollThread); secpollthread.detach(); } diff --git a/pdns/dnsdistdist/dnsdist.hh b/pdns/dnsdistdist/dnsdist.hh index cd1ef1880059..58b38cfc6bbd 100644 --- a/pdns/dnsdistdist/dnsdist.hh +++ b/pdns/dnsdistdist/dnsdist.hh @@ -38,6 +38,7 @@ #include "circular_buffer.hh" #include "dnscrypt.hh" #include "dnsdist-cache.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-dynbpf.hh" #include "dnsdist-idstate.hh" #include "dnsdist-lbpolicies.hh" @@ -59,10 +60,6 @@ uint64_t uptimeOfProcess(const std::string& str); -extern uint16_t g_ECSSourcePrefixV4; -extern uint16_t g_ECSSourcePrefixV6; -extern bool g_ECSOverride; - using QTag = std::unordered_map; class IncomingTCPConnectionState; @@ -72,7 +69,7 @@ struct ClientState; struct DNSQuestion { DNSQuestion(InternalQueryState& ids_, PacketBuffer& data_) : - data(data_), ids(ids_), ecsPrefixLength(ids.origRemote.sin4.sin_family == AF_INET ? g_ECSSourcePrefixV4 : g_ECSSourcePrefixV6), ecsOverride(g_ECSOverride) + data(data_), ids(ids_), ecsPrefixLength(ids.origRemote.sin4.sin_family == AF_INET ? dnsdist::configuration::getCurrentRuntimeConfiguration().d_ECSSourcePrefixV4 : dnsdist::configuration::getCurrentRuntimeConfiguration().d_ECSSourcePrefixV6), ecsOverride(dnsdist::configuration::getCurrentRuntimeConfiguration().d_ecsOverride) { } DNSQuestion(const DNSQuestion&) = delete; @@ -210,113 +207,6 @@ struct DNSResponse : DNSQuestion const std::shared_ptr& d_downstream; }; -/* so what could you do: - drop, - fake up nxdomain, - provide actual answer, - allow & and stop processing, - continue processing, - modify header: (servfail|refused|notimp), set TC=1, - send to pool */ - -class DNSAction -{ -public: - enum class Action : uint8_t - { - Drop, - Nxdomain, - Refused, - Spoof, - Allow, - HeaderModify, - Pool, - Delay, - Truncate, - ServFail, - None, - NoOp, - NoRecurse, - SpoofRaw, - SpoofPacket, - SetTag, - }; - static std::string typeToString(const Action& action) - { - switch (action) { - case Action::Drop: - return "Drop"; - case Action::Nxdomain: - return "Send NXDomain"; - case Action::Refused: - return "Send Refused"; - case Action::Spoof: - return "Spoof an answer"; - case Action::SpoofPacket: - return "Spoof a raw answer from bytes"; - case Action::SpoofRaw: - return "Spoof an answer from raw bytes"; - case Action::Allow: - return "Allow"; - case Action::HeaderModify: - return "Modify the header"; - case Action::Pool: - return "Route to a pool"; - case Action::Delay: - return "Delay"; - case Action::Truncate: - return "Truncate over UDP"; - case Action::ServFail: - return "Send ServFail"; - case Action::SetTag: - return "Set Tag"; - case Action::None: - case Action::NoOp: - return "Do nothing"; - case Action::NoRecurse: - return "Set rd=0"; - } - - return "Unknown"; - } - - virtual Action operator()(DNSQuestion*, string* ruleresult) const = 0; - virtual ~DNSAction() - { - } - virtual string toString() const = 0; - virtual std::map getStats() const - { - return {{}}; - } - virtual void reload() - { - } -}; - -class DNSResponseAction -{ -public: - enum class Action : uint8_t - { - Allow, - Delay, - Drop, - HeaderModify, - ServFail, - Truncate, - None - }; - virtual Action operator()(DNSResponse*, string* ruleresult) const = 0; - virtual ~DNSResponseAction() - { - } - virtual string toString() const = 0; - virtual void reload() - { - } -}; - struct DynBlock { DynBlock() @@ -386,8 +276,6 @@ struct DynBlock extern GlobalStateHolder> g_dynblockNMG; -extern vector> g_confDelta; - using pdns::stat_t; class BasicQPSLimiter @@ -502,23 +390,6 @@ private: bool d_passthrough{true}; }; -typedef std::unordered_map QueryCountRecords; -typedef std::function(const DNSQuestion* dq)> QueryCountFilter; -struct QueryCount -{ - QueryCount() - { - } - ~QueryCount() - { - } - SharedLockGuarded records; - QueryCountFilter filter; - bool enabled{false}; -}; - -extern QueryCount g_qcount; - class XskPacket; class XskSocket; class XskWorker; @@ -1091,10 +962,6 @@ public: } return latencyUsec; } - - static int s_udpTimeout; - static bool s_randomizeSockets; - static bool s_randomizeIDs; }; using servers_t = vector>; @@ -1157,7 +1024,6 @@ enum ednsHeaderFlags }; extern GlobalStateHolder> g_dynblockSMT; -extern DNSAction::Action g_dynBlockAction; extern GlobalStateHolder g_policy; extern GlobalStateHolder g_dstates; @@ -1171,27 +1037,6 @@ extern std::vector> g_dohlocals; extern std::vector> g_doqlocals; extern std::vector> g_doh3locals; extern std::vector> g_frontends; -extern bool g_truncateTC; -extern bool g_fixupCase; -extern int g_tcpRecvTimeout; -extern int g_tcpSendTimeout; -extern uint16_t g_maxOutstanding; -extern std::atomic g_configurationDone; -extern boost::optional g_maxTCPClientThreads; -extern uint64_t g_maxTCPQueuedConnections; -extern size_t g_maxTCPQueriesPerConn; -extern size_t g_maxTCPConnectionDuration; -extern size_t g_tcpInternalPipeBufferSize; -extern pdns::stat16_t g_cacheCleaningDelay; -extern pdns::stat16_t g_cacheCleaningPercentage; -extern uint32_t g_staleCacheEntriesTTL; -extern bool g_apiReadWrite; -extern std::string g_apiConfigDirectory; -extern bool g_servFailOnNoPolicy; -extern size_t g_udpVectorSize; -extern bool g_allowEmptyResponse; -extern uint32_t g_socketUDPSendBuffer; -extern uint32_t g_socketUDPRecvBuffer; extern shared_ptr g_defaultBPFFilter; extern std::vector> g_dynBPFFilters; @@ -1203,7 +1048,7 @@ void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ sid bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect void resetLuaSideEffect(); // reset to indeterminate state -bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote); +bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote, bool allowEmptyResponse); bool checkQueryHeaders(const struct dnsheader& dnsHeader, ClientState& clientState); @@ -1211,15 +1056,7 @@ extern std::vector> g_dnsCryptLocals; bool handleDNSCryptQuery(PacketBuffer& packet, DNSCryptQuery& query, bool tcp, time_t now, PacketBuffer& response); bool checkDNSCryptQuery(const ClientState& clientState, PacketBuffer& query, std::unique_ptr& dnsCryptQuery, time_t now, bool tcp); -#include "dnsdist-snmp.hh" - -extern bool g_snmpEnabled; -extern bool g_snmpTrapsEnabled; -extern std::unique_ptr g_snmpAgent; -extern bool g_addEDNSToSelfGeneratedResponses; - extern std::set g_capabilitiesToRetain; -static const uint16_t s_udpIncomingBufferSize{1500}; // don't accept UDP queries larger than this value enum class ProcessQueryResult : uint8_t { diff --git a/pdns/dnsdistdist/test-dnscrypt_cc.cc b/pdns/dnsdistdist/test-dnscrypt_cc.cc index fca9fd209de6..8b89539c2eb8 100644 --- a/pdns/dnsdistdist/test-dnscrypt_cc.cc +++ b/pdns/dnsdistdist/test-dnscrypt_cc.cc @@ -34,8 +34,6 @@ #include "dolog.hh" #include -bool g_verbose{false}; - BOOST_AUTO_TEST_SUITE(test_dnscrypt_cc) #ifdef HAVE_DNSCRYPT diff --git a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc index 0429e5c56090..6163e1aead23 100644 --- a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc @@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(test_Query) } { - BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_prefix_length(&lightDQ), g_ECSSourcePrefixV4); + BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_prefix_length(&lightDQ), dnsdist::configuration::getCurrentRuntimeConfiguration().d_ECSSourcePrefixV4); dnsdist_ffi_dnsquestion_set_ecs_prefix_length(&lightDQ, 65535); BOOST_CHECK_EQUAL(dnsdist_ffi_dnsquestion_get_ecs_prefix_length(&lightDQ), 65535U); } diff --git a/pdns/dnsdistdist/test-dnsdist_cc.cc b/pdns/dnsdistdist/test-dnsdist_cc.cc index a6fa8ff834ce..9fbdcbfd1af0 100644 --- a/pdns/dnsdistdist/test-dnsdist_cc.cc +++ b/pdns/dnsdistdist/test-dnsdist_cc.cc @@ -31,6 +31,7 @@ #include "dnsdist.hh" #include "dnsdist-ecs.hh" #include "dnsdist-internal-queries.hh" +#include "dnsdist-snmp.hh" #include "dnsdist-tcp.hh" #include "dnsdist-xsk.hh" @@ -1656,7 +1657,7 @@ BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) BOOST_CHECK_EQUAL(getEDNSUDPPayloadSizeAndZ(reinterpret_cast(dnsQuestion.getData().data()), dnsQuestion.getData().size(), &udpPayloadSize, &zValue), true); BOOST_CHECK_EQUAL(zValue, 0); - BOOST_CHECK_EQUAL(udpPayloadSize, g_PayloadSizeSelfGenAnswers); + BOOST_CHECK_EQUAL(udpPayloadSize, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers); } { @@ -1671,7 +1672,7 @@ BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) BOOST_CHECK_EQUAL(getEDNSUDPPayloadSizeAndZ(reinterpret_cast(dnsQuestion.getData().data()), dnsQuestion.getData().size(), &udpPayloadSize, &zValue), true); BOOST_CHECK_EQUAL(zValue, EDNS_HEADER_FLAG_DO); - BOOST_CHECK_EQUAL(udpPayloadSize, g_PayloadSizeSelfGenAnswers); + BOOST_CHECK_EQUAL(udpPayloadSize, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers); } { @@ -1686,7 +1687,7 @@ BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) BOOST_CHECK_EQUAL(getEDNSUDPPayloadSizeAndZ(reinterpret_cast(dnsQuestion.getData().data()), dnsQuestion.getData().size(), &udpPayloadSize, &zValue), true); BOOST_CHECK_EQUAL(zValue, 0); - BOOST_CHECK_EQUAL(udpPayloadSize, g_PayloadSizeSelfGenAnswers); + BOOST_CHECK_EQUAL(udpPayloadSize, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers); } { @@ -1701,7 +1702,7 @@ BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) BOOST_CHECK_EQUAL(getEDNSUDPPayloadSizeAndZ(reinterpret_cast(dnsQuestion.getData().data()), dnsQuestion.getData().size(), &udpPayloadSize, &zValue), true); BOOST_CHECK_EQUAL(zValue, EDNS_HEADER_FLAG_DO); - BOOST_CHECK_EQUAL(udpPayloadSize, g_PayloadSizeSelfGenAnswers); + BOOST_CHECK_EQUAL(udpPayloadSize, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers); } } diff --git a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc index 7d6569073cec..a3df9eff6a1d 100644 --- a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc @@ -10,19 +10,15 @@ #include "dnsdist.hh" #include "dnsdist-lua.hh" #include "dnsdist-lua-ffi.hh" +#include "dnsdist-snmp.hh" #include "dolog.hh" -uint16_t g_maxOutstanding{std::numeric_limits::max()}; - #include "ext/luawrapper/include/LuaContext.hpp" RecursiveLockGuarded g_lua{LuaContext()}; -bool g_snmpEnabled{false}; -bool g_snmpTrapsEnabled{false}; std::unique_ptr g_snmpAgent{nullptr}; #if BENCH_POLICIES -bool g_verbose{true}; #include "dnsdist-rings.hh" Rings g_rings; GlobalStateHolder> g_dynblockNMG; @@ -102,9 +98,6 @@ static DNSQuestion getDQ(const DNSName* providedName = nullptr) static void benchPolicy(const ServerPolicy& pol) { #if BENCH_POLICIES - bool existingVerboseValue = g_verbose; - g_verbose = false; - std::vector names; names.reserve(1000); for (size_t idx = 0; idx < 1000; idx++) { @@ -129,8 +122,6 @@ static void benchPolicy(const ServerPolicy& pol) } } cerr << pol.name << " took " << std::to_string(sw.udiff()) << " us for " << names.size() << endl; - - g_verbose = existingVerboseValue; #endif /* BENCH_POLICIES */ } @@ -223,17 +214,23 @@ BOOST_AUTO_TEST_CASE(test_roundRobin) ServerPolicy::NumberedServerVector servers; /* selecting a server on an empty server list */ - g_roundrobinFailOnNoServer = false; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_roundrobinFailOnNoServer = false; + }); auto server = pol.getSelectedBackend(servers, dnsQuestion); BOOST_CHECK(server == nullptr); servers.emplace_back(1, std::make_shared(ComboAddress("192.0.2.1:53"))); - /* servers start as 'down' but the RR policy returns a server unless g_roundrobinFailOnNoServer is set */ - g_roundrobinFailOnNoServer = true; + /* servers start as 'down' but the RR policy returns a server unless d_roundrobinFailOnNoServer is set */ + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_roundrobinFailOnNoServer = true; + }); server = pol.getSelectedBackend(servers, dnsQuestion); BOOST_CHECK(server == nullptr); - g_roundrobinFailOnNoServer = false; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_roundrobinFailOnNoServer = false; + }); server = pol.getSelectedBackend(servers, dnsQuestion); BOOST_CHECK(server != nullptr); @@ -466,8 +463,10 @@ BOOST_AUTO_TEST_CASE(test_whashed) BOOST_AUTO_TEST_CASE(test_chashed) { - bool existingVerboseValue = g_verbose; - g_verbose = false; + bool existingVerboseValue = dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_verbose = false; + }); std::vector names; names.reserve(1000); @@ -549,7 +548,9 @@ BOOST_AUTO_TEST_CASE(test_chashed) BOOST_CHECK_GT(got, expected / 2); BOOST_CHECK_LT(got, expected * 2); - g_verbose = existingVerboseValue; + dnsdist::configuration::updateRuntimeConfiguration([existingVerboseValue](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_verbose = existingVerboseValue; + }); } BOOST_AUTO_TEST_CASE(test_lua) @@ -822,9 +823,6 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_whashed) BOOST_AUTO_TEST_CASE(test_lua_ffi_chashed) { - bool existingVerboseValue = g_verbose; - g_verbose = false; - std::vector names; names.reserve(1000); for (size_t idx = 0; idx < 1000; idx++) { @@ -880,7 +878,6 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_chashed) benchPolicy(pol); } - g_verbose = existingVerboseValue; resetLuaContext(); } diff --git a/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc b/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc index c3f555a2257e..a24341f13ab6 100644 --- a/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc @@ -472,7 +472,6 @@ struct TestFixture /* we _NEED_ to set this function to empty otherwise we might get what was set by the last test, and we might not like it at all */ s_processQuery = nullptr; - g_proxyProtocolACL.clear(); } }; diff --git a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc index 2934616ff769..85cb05b2da8a 100644 --- a/pdns/dnsdistdist/test-dnsdisttcp_cc.cc +++ b/pdns/dnsdistdist/test-dnsdisttcp_cc.cc @@ -37,8 +37,6 @@ GlobalStateHolder g_ACL; GlobalStateHolder g_dstates; -QueryCount g_qcount; - const bool TCPIOHandler::s_disableConnectForUnitTests = true; bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::unique_ptr& dnsCryptQuery, time_t now, bool tcp) @@ -71,7 +69,7 @@ ProcessQueryResult processQuery(DNSQuestion& dq, LocalHolders& holders, std::sha return ProcessQueryResult::Drop; } -bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote) +bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr& remote, bool allowEmptyResponse) { return true; } @@ -456,8 +454,9 @@ struct TestFixture s_backendReadBuffer.clear(); s_backendWriteBuffer.clear(); - g_proxyProtocolACL.clear(); - g_verbose = false; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_proxyProtocolACL.clear(); + }); IncomingTCPConnectionState::clearAllDownstreamConnections(); /* we _NEED_ to set this function to empty otherwise we might get what was set @@ -482,6 +481,7 @@ static void testInit(const std::string& name, TCPClientThreadData& threadData) BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_SelfAnswered, TestFixture) { + const auto tcpRecvTimeout = dnsdist::configuration::getCurrentRuntimeConfiguration().d_tcpRecvTimeout; auto local = getBackendAddress("1", 80); ClientState localCS(local, true, false, 0, "", {}, true); auto tlsCtx = std::make_shared(); @@ -656,7 +656,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_SelfAnswered, TestFixture) state->handleIO(); BOOST_CHECK_EQUAL(threadData.mplexer->run(&now), 0); struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredReadConns = threadData.mplexer->getTimeouts(later, false); for (const auto& cbData : expiredReadConns) { BOOST_CHECK_EQUAL(cbData.first, state->d_handler.getDescriptor()); @@ -692,7 +692,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_SelfAnswered, TestFixture) state->handleIO(); BOOST_CHECK_EQUAL(threadData.mplexer->run(&now), 0); struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredWriteConns = threadData.mplexer->getTimeouts(later, true); for (const auto& cbData : expiredWriteConns) { BOOST_CHECK_EQUAL(cbData.first, state->d_handler.getDescriptor()); @@ -729,6 +729,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_SelfAnswered, TestFixture) BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered, TestFixture) { + const auto tcpRecvTimeout = dnsdist::configuration::getCurrentRuntimeConfiguration().d_tcpRecvTimeout; auto local = getBackendAddress("1", 80); ClientState localCS(local, true, false, 0, "", {}, true); auto tlsCtx = std::make_shared(); @@ -751,8 +752,10 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered, T { TEST_INIT("=> reading PP"); - g_proxyProtocolACL.addMask("0.0.0.0/0"); - g_proxyProtocolACL.addMask("::0/0"); + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_proxyProtocolACL.addMask("0.0.0.0/0"); + config.d_proxyProtocolACL.addMask("::0/0"); + }); auto proxyPayload = makeProxyHeader(true, ComboAddress("192.0.2.1"), ComboAddress("192.0.2.2"), {}); BOOST_REQUIRE_GT(proxyPayload.size(), s_proxyProtocolMinimumHeaderSize); @@ -791,8 +794,11 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered, T { TEST_INIT("=> Invalid PP"); - g_proxyProtocolACL.addMask("0.0.0.0/0"); - g_proxyProtocolACL.addMask("::0/0"); + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_proxyProtocolACL.addMask("0.0.0.0/0"); + config.d_proxyProtocolACL.addMask("::0/0"); + }); + auto proxyPayload = std::vector(s_proxyProtocolMinimumHeaderSize); std::fill(proxyPayload.begin(), proxyPayload.end(), 0); @@ -818,8 +824,11 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered, T { TEST_INIT("=> timeout while reading PP"); - g_proxyProtocolACL.addMask("0.0.0.0/0"); - g_proxyProtocolACL.addMask("::0/0"); + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_proxyProtocolACL.addMask("0.0.0.0/0"); + config.d_proxyProtocolACL.addMask("::0/0"); + }); + auto proxyPayload = makeProxyHeader(true, ComboAddress("192.0.2.1"), ComboAddress("192.0.2.2"), {}); BOOST_REQUIRE_GT(proxyPayload.size(), s_proxyProtocolMinimumHeaderSize); s_readBuffer = query; @@ -843,7 +852,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionWithProxyProtocol_SelfAnswered, T state->handleIO(); BOOST_CHECK_EQUAL(threadData.mplexer->run(&now), 0); struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredReadConns = threadData.mplexer->getTimeouts(later, false); for (const auto& cbData : expiredReadConns) { BOOST_CHECK_EQUAL(cbData.first, state->d_handler.getDescriptor()); @@ -1660,7 +1669,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_BackendNoOOOR, TestFixture) /* 101 queries on the same connection, check that the maximum number of queries kicks in */ TEST_INIT("=> 101 queries on the same connection"); - g_maxTCPQueriesPerConn = 100; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_maxTCPQueriesPerConn = 100; + }); size_t count = 101; @@ -1714,7 +1725,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_BackendNoOOOR, TestFixture) /* we need to clear them now, otherwise we end up with dangling pointers to the steps via the TLS context, etc */ IncomingTCPConnectionState::clearAllDownstreamConnections(); - g_maxTCPQueriesPerConn = 0; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_maxTCPQueriesPerConn = 0; + }); #endif } @@ -1759,6 +1772,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_BackendNoOOOR, TestFixture) BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) { + const auto tcpRecvTimeout = dnsdist::configuration::getCurrentRuntimeConfiguration().d_tcpRecvTimeout; auto local = getBackendAddress("1", 80); ClientState localCS(local, true, false, 0, "", {}, true); /* enable out-of-order on the front side */ @@ -1952,7 +1966,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) TEST_INIT("=> 3 queries sent to the backend, 1 self-answered, 1 new query sent to the backend which responds to the first query right away, then to the last one, then the connection to the backend times out"); // increase the client timeout for that test, we want the backend to timeout first - g_tcpRecvTimeout = 5; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_tcpRecvTimeout = 5; + }); PacketBuffer expectedWriteBuffer; PacketBuffer expectedBackendWriteBuffer; @@ -2092,7 +2108,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) IncomingTCPConnectionState::clearAllDownstreamConnections(); // restore the client timeout - g_tcpRecvTimeout = 2; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_tcpRecvTimeout = 2; + }); } { @@ -2252,7 +2270,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) } struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredConns = threadData.mplexer->getTimeouts(later, false); BOOST_CHECK_EQUAL(expiredConns.size(), 1U); for (const auto& cbData : expiredConns) { @@ -2527,7 +2545,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) } struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredConns = threadData.mplexer->getTimeouts(later, false); BOOST_CHECK_EQUAL(expiredConns.size(), 1U); for (const auto& cbData : expiredConns) { @@ -2543,7 +2561,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) } later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; expiredConns = threadData.mplexer->getTimeouts(later, false); BOOST_CHECK_EQUAL(expiredConns.size(), 1U); for (const auto& cbData : expiredConns) { @@ -3557,7 +3575,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) /* make sure that the backend's timeout is shorter than the client's */ backend->d_config.tcpConnectTimeout = 1; - g_tcpRecvTimeout = 5; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_tcpRecvTimeout = 5; + }); bool timeout = false; s_steps = { @@ -3616,7 +3636,9 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) /* restore */ backend->d_config.tcpSendTimeout = 30; - g_tcpRecvTimeout = 2; + dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) { + config.d_tcpRecvTimeout = 2; + }); /* we need to clear them now, otherwise we end up with dangling pointers to the steps via the TLS context, etc */ /* we have no connection to clear, because there was a timeout! */ @@ -3876,7 +3898,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) } struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredConns = threadData.mplexer->getTimeouts(later); BOOST_CHECK_EQUAL(expiredConns.size(), 1U); for (const auto& cbData : expiredConns) { @@ -3899,6 +3921,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendOOOR, TestFixture) BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendNotOOOR, TestFixture) { + const auto tcpRecvTimeout = dnsdist::configuration::getCurrentRuntimeConfiguration().d_tcpRecvTimeout; auto local = getBackendAddress("1", 80); ClientState localCS(local, true, false, 0, "", {}, true); /* enable out-of-order on the front side */ @@ -4160,7 +4183,7 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnectionOOOR_BackendNotOOOR, TestFixture) } struct timeval later = now; - later.tv_sec += g_tcpRecvTimeout + 1; + later.tv_sec += tcpRecvTimeout + 1; auto expiredConns = threadData.mplexer->getTimeouts(later); BOOST_CHECK_EQUAL(expiredConns.size(), 1U); for (const auto& cbData : expiredConns) { diff --git a/pdns/dolog.hh b/pdns/dolog.hh index 25c49521b7e3..2552db568439 100644 --- a/pdns/dolog.hh +++ b/pdns/dolog.hh @@ -46,7 +46,7 @@ errlog("Unable to bind to %s: %s", ca.toStringWithPort(), strerr(errno)); Will log to stdout. Will syslog in any case with LOG_INFO, - LOG_WARNING, LOG_ERR respectively. If g_verbose=false, vinfolog is a noop. + LOG_WARNING, LOG_ERR respectively. If verbose=false, vinfolog is a noop. More generically, dolog(someiostream, "Hello %s", stream) will log to someiostream This will happily print a string to %d! Doesn't do further format processing. @@ -81,9 +81,6 @@ void dolog(O& outputStream, const char* formatStr, T value, const Args&... args) } #if !defined(RECURSOR) -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -extern bool g_verbose; - #ifdef DNSDIST namespace dnsdist::logging { @@ -96,10 +93,6 @@ public: ISO8601 }; - static void setVerbose(bool value = true) - { - g_verbose = value; - } static void setSyslog(bool value = true) { s_syslog = value; @@ -123,10 +116,6 @@ public: { s_verboseStream = std::move(stream); } - static bool getVerbose() - { - return g_verbose; - } static bool getSyslog() { return s_syslog; @@ -235,9 +224,16 @@ void verboselog(const char* formatStr, const Args&... args) #endif /* DNSDIST */ } -#define vinfolog \ - if (g_verbose) \ +#ifdef DNSDIST +#include "dnsdist-configuration.hh" + +#define vinfolog \ + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose) \ verboselog +#else +#define vinfolog \ + infolog +#endif template void infolog(const char* formatStr, const Args&... args) @@ -258,9 +254,8 @@ void errlog(const char* formatStr, const Args&... args) } #else // RECURSOR -#define g_verbose 0 #define vinfolog \ - if (g_verbose) \ + if (false) \ infolog template diff --git a/pdns/proxy-protocol.hh b/pdns/proxy-protocol.hh index a44c72110f5c..5c20d3b9c589 100644 --- a/pdns/proxy-protocol.hh +++ b/pdns/proxy-protocol.hh @@ -37,7 +37,7 @@ struct ProxyProtocolValue enum class Types : uint8_t { PP_TLV_ALPN = 0x01, PP_TLV_SSL = 0x20 }; }; -static const size_t s_proxyProtocolMinimumHeaderSize = 16; +static constexpr size_t s_proxyProtocolMinimumHeaderSize = 16; std::string makeLocalProxyHeader(); std::string makeProxyHeader(bool tcp, const ComboAddress& source, const ComboAddress& destination, const std::vector& values); diff --git a/pdns/tcpiohandler.cc b/pdns/tcpiohandler.cc index edee311ad078..81107cbc068e 100644 --- a/pdns/tcpiohandler.cc +++ b/pdns/tcpiohandler.cc @@ -7,6 +7,19 @@ const bool TCPIOHandler::s_disableConnectForUnitTests = false; +namespace { +bool shouldDoVerboseLogging() +{ +#ifdef DNSDIST + return dnsdist::configuration::getCurrentRuntimeConfiguration().d_verbose; +#elif defined(RECURSOR) + return false; +#else + return true; +#endif +} +} + #ifdef HAVE_LIBSODIUM #include #endif /* HAVE_LIBSODIUM */ @@ -83,7 +96,7 @@ class OpenSSLTLSConnection: public TLSConnection if (!d_conn) { vinfolog("Error creating TLS object"); - if (g_verbose) { + if (shouldDoVerboseLogging()) { ERR_print_errors_fp(stderr); } throw std::runtime_error("Error creating TLS object"); @@ -103,7 +116,7 @@ class OpenSSLTLSConnection: public TLSConnection if (!d_conn) { vinfolog("Error creating TLS object"); - if (g_verbose) { + if (shouldDoVerboseLogging()) { ERR_print_errors_fp(stderr); } throw std::runtime_error("Error creating TLS object"); @@ -201,7 +214,7 @@ class OpenSSLTLSConnection: public TLSConnection } #endif else { - if (g_verbose) { + if (shouldDoVerboseLogging()) { throw std::runtime_error("Error while processing TLS connection: (" + std::to_string(error) + ") " + libssl_get_error_string()); } else { throw std::runtime_error("Error while processing TLS connection: " + std::to_string(error)); diff --git a/pdns/tcpiohandler.hh b/pdns/tcpiohandler.hh index 8420529811e3..191a161e5c5f 100644 --- a/pdns/tcpiohandler.hh +++ b/pdns/tcpiohandler.hh @@ -566,7 +566,7 @@ public: return d_conn->getAsyncFDs(); } - const static bool s_disableConnectForUnitTests; + static const bool s_disableConnectForUnitTests; private: std::unique_ptr d_conn{nullptr};