From: Remi Gacogne Date: Mon, 4 Mar 2024 10:17:46 +0000 (+0100) Subject: dnsdist: Format moved files X-Git-Tag: dnsdist-1.10.0-alpha0~8^2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=086114d52965c6d0334f46617c2964ff71db2642;p=thirdparty%2Fpdns.git dnsdist: Format moved files --- diff --git a/.not-formatted b/.not-formatted index 759460e7fd..050ad15f10 100644 --- a/.not-formatted +++ b/.not-formatted @@ -36,31 +36,6 @@ ./pdns/dnscrypt.cc ./pdns/dnscrypt.hh ./pdns/dnsdemog.cc -./pdns/dnsdist-cache.cc -./pdns/dnsdist-cache.hh -./pdns/dnsdist-console.cc -./pdns/dnsdist-console.hh -./pdns/dnsdist-dynbpf.cc -./pdns/dnsdist-dynbpf.hh -./pdns/dnsdist-ecs.cc -./pdns/dnsdist-ecs.hh -./pdns/dnsdist-lbpolicies.hh -./pdns/dnsdist-lua-bindings-dnsquestion.cc -./pdns/dnsdist-lua-bindings.cc -./pdns/dnsdist-lua-inspection.cc -./pdns/dnsdist-lua-rules.cc -./pdns/dnsdist-lua-vars.cc -./pdns/dnsdist-lua.hh -./pdns/dnsdist-rings.cc -./pdns/dnsdist-rings.hh -./pdns/dnsdist-snmp.cc -./pdns/dnsdist-snmp.hh -./pdns/dnsdist-tcp.cc -./pdns/dnsdist-web.cc -./pdns/dnsdist-xpf.cc -./pdns/dnsdist-xpf.hh -./pdns/dnsdist.cc -./pdns/dnsdist.hh ./pdns/dnsdistdist/connection-management.hh ./pdns/dnsdistdist/dnsdist-backend.cc ./pdns/dnsdistdist/dnsdist-kvs.cc @@ -232,8 +207,6 @@ ./pdns/test-common.hh ./pdns/test-distributor_hh.cc ./pdns/test-dnscrypt_cc.cc -./pdns/test-dnsdist_cc.cc -./pdns/test-dnsdistpacketcache_cc.cc ./pdns/test-dnsname_cc.cc ./pdns/test-dnsparser_cc.cc ./pdns/test-dnsparser_hh.cc diff --git a/pdns/dnsdistdist/dnsdist-cache.cc b/pdns/dnsdistdist/dnsdist-cache.cc index c3b0e75ef6..62d84b7d63 100644 --- a/pdns/dnsdistdist/dnsdist-cache.cc +++ b/pdns/dnsdistdist/dnsdist-cache.cc @@ -29,7 +29,8 @@ #include "ednssubnet.hh" #include "packetcache.hh" -DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t maxNegativeTTL, uint32_t staleTTL, bool dontAge, uint32_t shards, bool deferrableInsertLock, bool parseECS): d_maxEntries(maxEntries), d_shardCount(shards), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_maxNegativeTTL(maxNegativeTTL), d_minTTL(minTTL), d_staleTTL(staleTTL), d_dontAge(dontAge), d_deferrableInsertLock(deferrableInsertLock), d_parseECS(parseECS) +DNSDistPacketCache::DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL, uint32_t minTTL, uint32_t tempFailureTTL, uint32_t maxNegativeTTL, uint32_t staleTTL, bool dontAge, uint32_t shards, bool deferrableInsertLock, bool parseECS) : + d_maxEntries(maxEntries), d_shardCount(shards), d_maxTTL(maxTTL), d_tempFailureTTL(tempFailureTTL), d_maxNegativeTTL(maxNegativeTTL), d_minTTL(minTTL), d_staleTTL(staleTTL), d_dontAge(dontAge), d_deferrableInsertLock(deferrableInsertLock), d_parseECS(parseECS) { if (d_maxEntries == 0) { throw std::runtime_error("Trying to create a 0-sized packet-cache"); @@ -83,14 +84,14 @@ bool DNSDistPacketCache::cachedValueMatches(const CacheValue& cachedValue, uint1 return true; } -void DNSDistPacketCache::insertLocked(CacheShard& shard, std::unordered_map& map, uint32_t key, CacheValue& newValue) +void DNSDistPacketCache::insertLocked(CacheShard& shard, std::unordered_map& map, uint32_t key, CacheValue& newValue) { /* check again now that we hold the lock to prevent a race */ if (map.size() >= (d_maxEntries / d_shardCount)) { return; } - std::unordered_map::iterator it; + std::unordered_map::iterator it; bool result; std::tie(it, result) = map.insert({key, newValue}); @@ -227,7 +228,7 @@ bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut return false; } - std::unordered_map::const_iterator it = map->find(key); + std::unordered_map::const_iterator it = map->find(key); if (it == map->end()) { if (recordMiss) { ++d_misses; @@ -298,7 +299,7 @@ bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut if (!stale) { // coverity[store_truncates_time_t] dnsheader_aligned dh_aligned(response.data()); - ageDNSPacket(reinterpret_cast(&response[0]), response.size(), age, dh_aligned); + ageDNSPacket(reinterpret_cast(&response[0]), response.size(), age, dh_aligned); } else { editDNSPacketTTL(reinterpret_cast(&response[0]), response.size(), @@ -330,7 +331,7 @@ size_t DNSDistPacketCache::purgeExpired(size_t upTo, const time_t now) size_t toRemove = map->size() - maxPerShard; - for (auto it = map->begin(); toRemove > 0 && it != map->end(); ) { + for (auto it = map->begin(); toRemove > 0 && it != map->end();) { const CacheValue& value = it->second; if (value.validity <= now) { @@ -338,7 +339,8 @@ size_t DNSDistPacketCache::purgeExpired(size_t upTo, const time_t now) --toRemove; --shard.d_entriesCount; ++removed; - } else { + } + else { ++it; } } @@ -393,14 +395,15 @@ size_t DNSDistPacketCache::expungeByName(const DNSName& name, uint16_t qtype, bo for (auto& shard : d_shards) { auto map = shard.d_map.write_lock(); - for(auto it = map->begin(); it != map->end(); ) { + for (auto it = map->begin(); it != map->end();) { const CacheValue& value = it->second; if ((value.qname == name || (suffixMatch && value.qname.isPartOf(name))) && (qtype == QType::ANY || qtype == value.qtype)) { it = map->erase(it); --shard.d_entriesCount; ++removed; - } else { + } + else { ++it; } } @@ -411,7 +414,7 @@ size_t DNSDistPacketCache::expungeByName(const DNSName& name, uint16_t qtype, bo bool DNSDistPacketCache::isFull() { - return (getSize() >= d_maxEntries); + return (getSize() >= d_maxEntries); } uint64_t DNSDistPacketCache::getSize() @@ -435,11 +438,11 @@ uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qname uint32_t result = 0; /* skip the query ID */ if (packet.size() < sizeof(dnsheader)) { - throw std::range_error("Computing packet cache key for an invalid packet size (" + std::to_string(packet.size()) +")"); + throw std::range_error("Computing packet cache key for an invalid packet size (" + std::to_string(packet.size()) + ")"); } result = burtle(&packet.at(2), sizeof(dnsheader) - 2, result); - result = burtleCI((const unsigned char*) qname.c_str(), qname.length(), result); + result = burtleCI((const unsigned char*)qname.c_str(), qname.length(), result); if (packet.size() < sizeof(dnsheader) + qnameWireLength) { throw std::range_error("Computing packet cache key for an invalid packet (" + std::to_string(packet.size()) + " < " + std::to_string(sizeof(dnsheader) + qnameWireLength) + ")"); } @@ -452,7 +455,7 @@ uint32_t DNSDistPacketCache::getKey(const DNSName::string_t& qname, size_t qname result = burtle(&packet.at(sizeof(dnsheader) + qnameWireLength), packet.size() - (sizeof(dnsheader) + qnameWireLength), result); } } - result = burtle((const unsigned char*) &receivedOverUDP, sizeof(receivedOverUDP), result); + result = burtle((const unsigned char*)&receivedOverUDP, sizeof(receivedOverUDP), result); return result; } @@ -473,7 +476,7 @@ uint64_t DNSDistPacketCache::getEntriesCount() uint64_t DNSDistPacketCache::dump(int fd) { - auto fp = std::unique_ptr(fdopen(dup(fd), "w"), fclose); + auto fp = std::unique_ptr(fdopen(dup(fd), "w"), fclose); if (fp == nullptr) { return 0; } @@ -499,7 +502,7 @@ uint64_t DNSDistPacketCache::dump(int fd) fprintf(fp.get(), "%s %" PRId64 " %s ; rcode %" PRIu8 ", key %" PRIu32 ", length %" PRIu16 ", received over UDP %d, added %" PRId64 "\n", value.qname.toString().c_str(), static_cast(value.validity - now), QType(value.qtype).toString().c_str(), rcode, entry.first, value.len, value.receivedOverUDP, static_cast(value.added)); } - catch(...) { + catch (...) { fprintf(fp.get(), "; error printing '%s'\n", value.qname.empty() ? "EMPTY" : value.qname.toString().c_str()); } } diff --git a/pdns/dnsdistdist/dnsdist-cache.hh b/pdns/dnsdistdist/dnsdist-cache.hh index 95667bd4cd..3db5e6ab1f 100644 --- a/pdns/dnsdistdist/dnsdist-cache.hh +++ b/pdns/dnsdistdist/dnsdist-cache.hh @@ -35,13 +35,13 @@ struct DNSQuestion; class DNSDistPacketCache : boost::noncopyable { public: - DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t maxNegativeTTL=3600, uint32_t staleTTL=60, bool dontAge=false, uint32_t shards=1, bool deferrableInsertLock=true, bool parseECS=false); + DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL = 86400, uint32_t minTTL = 0, uint32_t tempFailureTTL = 60, uint32_t maxNegativeTTL = 3600, uint32_t staleTTL = 60, bool dontAge = false, uint32_t shards = 1, bool deferrableInsertLock = true, bool parseECS = false); void insert(uint32_t key, const boost::optional& subnet, uint16_t queryFlags, bool dnssecOK, const DNSName& qname, uint16_t qtype, uint16_t qclass, const PacketBuffer& response, bool receivedOverUDP, uint8_t rcode, boost::optional tempFailureTTL); bool get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut, boost::optional& subnet, bool dnssecOK, bool receivedOverUDP, uint32_t allowExpired = 0, bool skipAging = false, bool truncatedOK = true, bool recordMiss = true); size_t purgeExpired(size_t upTo, const time_t now); - size_t expunge(size_t upTo=0); - size_t expungeByName(const DNSName& name, uint16_t qtype=QType::ANY, bool suffixMatch=false); + size_t expunge(size_t upTo = 0); + size_t expungeByName(const DNSName& name, uint16_t qtype = QType::ANY, bool suffixMatch = false); bool isFull(); string toString(); uint64_t getSize(); @@ -89,7 +89,6 @@ public: static bool getClientSubnet(const PacketBuffer& packet, size_t qnameWireLength, boost::optional& subnet); private: - struct CacheValue { time_t getTTD() const { return validity; } @@ -121,13 +120,13 @@ private: d_map.write_lock()->reserve(maxSize); } - SharedLockGuarded> d_map; + SharedLockGuarded> d_map; std::atomic d_entriesCount{0}; }; bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool receivedOverUDP, bool dnssecOK, const boost::optional& subnet) const; uint32_t getShardIndex(uint32_t key) const; - void insertLocked(CacheShard& shard, std::unordered_map& map, uint32_t key, CacheValue& newValue); + void insertLocked(CacheShard& shard, std::unordered_map& map, uint32_t key, CacheValue& newValue); std::vector d_shards; std::unordered_set d_optionsToSkip{EDNSOptionCode::COOKIE}; diff --git a/pdns/dnsdistdist/dnsdist-console.cc b/pdns/dnsdistdist/dnsdist-console.cc index f40abb3446..a175cae261 100644 --- a/pdns/dnsdistdist/dnsdist-console.cc +++ b/pdns/dnsdistdist/dnsdist-console.cc @@ -27,7 +27,7 @@ #include #ifdef HAVE_LIBEDIT -#if defined (__OpenBSD__) || defined(__NetBSD__) +#if defined(__OpenBSD__) || defined(__NetBSD__) // If this is not undeffed, __attribute__ wil be redefined by /usr/include/readline/rlstdc.h #undef __STRICT_ANSI__ #include @@ -47,7 +47,7 @@ #include "threadname.hh" GlobalStateHolder g_consoleACL; -vector > g_confDelta; +vector> g_confDelta; std::string g_consoleKey; bool g_logConsoleConnections{true}; bool g_consoleEnabled{false}; @@ -58,13 +58,15 @@ static ConcurrentConnectionManager s_connManager(100); class ConsoleConnection { public: - ConsoleConnection(const ComboAddress& client, FDWrapper&& fileDesc): d_client(client), d_fileDesc(std::move(fileDesc)) + ConsoleConnection(const ComboAddress& client, FDWrapper&& fileDesc) : + d_client(client), d_fileDesc(std::move(fileDesc)) { if (!s_connManager.registerConnection()) { throw std::runtime_error("Too many concurrent console connections"); } } - ConsoleConnection(ConsoleConnection&& rhs) noexcept: d_client(rhs.d_client), d_fileDesc(std::move(rhs.d_fileDesc)) + ConsoleConnection(ConsoleConnection&& rhs) noexcept : + d_client(rhs.d_client), d_fileDesc(std::move(rhs.d_fileDesc)) { } @@ -111,17 +113,17 @@ static void feedConfigDelta(const std::string& line) } #ifdef HAVE_LIBEDIT -static string historyFile(const bool &ignoreHOME = false) +static string historyFile(const bool& ignoreHOME = false) { string ret; passwd pwd{}; - passwd *result{nullptr}; + passwd* result{nullptr}; std::array buf{}; getpwuid_r(geteuid(), &pwd, buf.data(), buf.size(), &result); // NOLINTNEXTLINE(concurrency-mt-unsafe): we are not modifying the environment - const char *homedir = getenv("HOME"); + const char* homedir = getenv("HOME"); if (result != nullptr) { ret = string(pwd.pw_dir); } @@ -136,7 +138,8 @@ static string historyFile(const bool &ignoreHOME = false) } #endif /* HAVE_LIBEDIT */ -enum class ConsoleCommandResult : uint8_t { +enum class ConsoleCommandResult : uint8_t +{ Valid = 0, ConnectionClosed, TooLarge @@ -166,13 +169,12 @@ static ConsoleCommandResult getMsgLen32(int fileDesc, uint32_t* len) static bool putMsgLen32(int fileDesc, uint32_t len) { - try - { + try { uint32_t raw = htonl(len); size_t ret = writen2(fileDesc, &raw, sizeof raw); return ret == sizeof raw; } - catch(...) { + catch (...) { return false; } } @@ -182,7 +184,7 @@ static ConsoleCommandResult sendMessageToServer(int fileDesc, const std::string& string msg = dnsdist::crypto::authenticated::encryptSym(line, g_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; + cerr << "Encrypted message is too long to be sent to the server, " << std::to_string(msgLen) << " > " << std::numeric_limits::max() << endl; return ConsoleCommandResult::TooLarge; } @@ -229,12 +231,12 @@ void doClient(ComboAddress server, const std::string& command) } if (g_verbose) { - cout<<"Connecting to "< "); - rl_bind_key('\t',rl_complete); + rl_bind_key('\t', rl_complete); if (sline == nullptr) { break; } @@ -288,7 +290,7 @@ void doClient(ComboAddress server, const std::string& command) string line(sline); if (!line.empty() && line != lastline) { add_history(sline); - history << sline < getNextConsoleLine(ofstream& history, std::str string line(sline); if (!line.empty() && line != lastline) { add_history(sline); - history << sline <, ClientState*, - std::unordered_map - > - > - >(withReturn ? ("return "+*line) : *line); + std::unordered_map>>>(withReturn ? ("return " + *line) : *line); if (ret) { if (const auto* dsValue = boost::get>(&*ret)) { if (*dsValue) { - cout<<(*dsValue)->getName()<getName() << endl; } } else if (const auto* csValue = boost::get(&*ret)) { if (*csValue != nullptr) { - cout<<(*csValue)->local.toStringWithPort()<local.toStringWithPort() << endl; } } else if (const auto* strValue = boost::get(&*ret)) { - cout<<*strValue< >(&*ret)) { + else if (const auto* mapValue = boost::get>(&*ret)) { using namespace json11; Json::object obj; for (const auto& value : *mapValue) { obj[value.first] = value.second; } Json out = obj; - cout< g_consoleKeywords{ +const std::vector g_consoleKeywords +{ /* keyword, function, parameters, description */ - { "addACL", true, "netmask", "add to the ACL set who can use this server" }, - { "addAction", true, R"(DNS rule, DNS action [, {uuid="UUID", name="name"}])", "add a rule" }, - { "addBPFFilterDynBlocks", true, "addresses, dynbpf[[, seconds=10], msg]", "This is the eBPF equivalent of addDynBlocks(), blocking a set of addresses for (optionally) a number of seconds, using an eBPF dynamic filter" }, - { "addCapabilitiesToRetain", true, "capability or list of capabilities", "Linux capabilities to retain after startup, like CAP_BPF" }, - { "addConsoleACL", true, "netmask", "add a netmask to the console ACL" }, - { "addDNSCryptBind", true, R"('127.0.0.1:8443", "provider name", "/path/to/resolver.cert", "/path/to/resolver.key", {reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}})", "listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of `provider name`, using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth optional parameter is a table of parameters" }, - { "addDOHLocal", true, "addr, certFile, keyFile [, urls [, vars]]", "listen to incoming DNS over HTTPS queries on the specified address using the specified certificate and key. The last two parameters are tables" }, - { "addDOH3Local", true, "addr, certFile, keyFile [, vars]", "listen to incoming DNS over HTTP/3 queries on the specified address using the specified certificate and key. The last parameter is a table" }, - { "addDOQLocal", true, "addr, certFile, keyFile [, vars]", "listen to incoming DNS over QUIC queries on the specified address using the specified certificate and key. The last parameter is a table" }, - { "addDynamicBlock", true, "address, message[, action [, seconds [, clientIPMask [, clientIPPortMask]]]]", "block the supplied address with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" }, - { "addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" }, - { "addDynBlockSMT", true, "names, message[, seconds [, action]]", "block the set of names with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)" }, - { "addLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "add `addr` to the list of addresses we listen on" }, - { "addCacheHitResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache hit response rule" }, - { "addCacheInsertedResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache inserted response rule" }, - { "addMaintenanceCallback", true, "callback", "register a function to be called as part of the maintenance hook, every second" }, - { "addResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a response rule" }, - { "addSelfAnsweredResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a self-answered response rule" }, - { "addTLSLocal", true, "addr, certFile(s), keyFile(s) [,params]", "listen to incoming DNS over TLS queries on the specified address using the specified certificate (or list of) and key (or list of). The last parameter is a table" }, - { "AllowAction", true, "", "let these packets go through" }, - { "AllowResponseAction", true, "", "let these packets go through" }, - { "AllRule", true, "", "matches all traffic" }, - { "AndRule", true, "list of DNS rules", "matches if all sub-rules matches" }, - { "benchRule", true, "DNS Rule [, iterations [, suffix]]", "bench the specified DNS rule" }, - { "carbonServer", true, "serverIP, [ourname], [interval]", "report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds" }, - { "clearConsoleHistory", true, "", "clear the internal (in-memory) history of console commands" }, - { "clearDynBlocks", true, "", "clear all dynamic blocks" }, - { "clearQueryCounters", true, "", "clears the query counter buffer" }, - { "clearRules", true, "", "remove all current rules" }, - { "controlSocket", true, "addr", "open a control socket on this address / connect to this address in client mode" }, - { "ContinueAction", true, "action", "execute the specified action and continue the processing of the remaining rules, regardless of the return of the action" }, - { "declareMetric", true, "name, type, description [, prometheusName]", "Declare a custom metric" }, - { "decMetric", true, "name", "Decrement a custom metric" }, - { "DelayAction", true, "milliseconds", "delay the response by the specified amount of milliseconds (UDP-only)" }, - { "DelayResponseAction", true, "milliseconds", "delay the response by the specified amount of milliseconds (UDP-only)" }, - { "delta", true, "", "shows all commands entered that changed the configuration" }, - { "DNSSECRule", true, "", "matches queries with the DO bit set" }, - { "DnstapLogAction", true, "identity, FrameStreamLogger [, alterFunction]", "send the contents of this query to a FrameStreamLogger or RemoteLogger as dnstap. `alterFunction` is a callback, receiving a DNSQuestion and a DnstapMessage, that can be used to modify the dnstap message" }, - { "DnstapLogResponseAction", true, "identity, FrameStreamLogger [, alterFunction]", "send the contents of this response to a remote or FrameStreamLogger or RemoteLogger as dnstap. `alterFunction` is a callback, receiving a DNSResponse and a DnstapMessage, that can be used to modify the dnstap message" }, - { "DropAction", true, "", "drop these packets" }, - { "DropResponseAction", true, "", "drop these packets" }, - { "DSTPortRule", true, "port", "matches questions received to the destination port specified" }, - { "dumpStats", true, "", "print all statistics we gather" }, - { "dynBlockRulesGroup", true, "", "return a new DynBlockRulesGroup object" }, - { "EDNSVersionRule", true, "version", "matches queries with the specified EDNS version" }, - { "EDNSOptionRule", true, "optcode", "matches queries with the specified EDNS0 option present" }, - { "ERCodeAction", true, "ercode", "Reply immediately by turning the query into a response with the specified EDNS extended rcode" }, - { "ERCodeRule", true, "rcode", "matches responses with the specified extended rcode (EDNS0)" }, - { "exceedNXDOMAINs", true, "rate, seconds", "get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds" }, - { "exceedQRate", true, "rate, seconds", "get set of address that exceed `rate` queries/s over `seconds` seconds" }, - { "exceedQTypeRate", true, "type, rate, seconds", "get set of address that exceed `rate` queries/s for queries of type `type` over `seconds` seconds" }, - { "exceedRespByterate", true, "rate, seconds", "get set of addresses that exceeded `rate` bytes/s answers over `seconds` seconds" }, - { "exceedServFails", true, "rate, seconds", "get set of addresses that exceed `rate` servfails/s over `seconds` seconds" }, - { "firstAvailable", false, "", "picks the server with the lowest `order` that has not exceeded its QPS limit" }, - { "fixupCase", true, "bool", "if set (default to no), rewrite the first qname of the question part of the answer to match the one from the query. It is only useful when you have a downstream server that messes up the case of the question qname in the answer" }, - { "generateDNSCryptCertificate", true, R"("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil)", "generate a new resolver private key and related certificate, valid from the `validFrom` timestamp until the `validUntil` one, signed with the provider private key" }, - { "generateDNSCryptProviderKeys", true, R"("/path/to/providerPublic.key", "/path/to/providerPrivate.key")", "generate a new provider keypair" }, - { "getAction", true, "n", "Returns the Action associated with rule n" }, - { "getBind", true, "n", "returns the listener at index n" }, - { "getBindCount", true, "", "returns the number of listeners all kinds" }, - { "getCacheHitResponseRule", true, "selector", "Return the cache-hit response rule corresponding to the selector, if any" }, - { "getCacheInsertedResponseRule", true, "selector", "Return the cache-inserted response rule corresponding to the selector, if any" }, - { "getCurrentTime", true, "", "returns the current time" }, - { "getDynamicBlocks", true, "", "returns a table of the current network-based dynamic blocks" }, - { "getDynamicBlocksSMT", true, "", "returns a table of the current suffix-based dynamic blocks" }, - { "getDNSCryptBind", true, "n", "return the `DNSCryptContext` object corresponding to the bind `n`" }, - { "getDNSCryptBindCount", true, "", "returns the number of DNSCrypt listeners" }, - { "getDOHFrontend", true, "n", "returns the DoH frontend with index n" }, - { "getDOHFrontendCount", true, "", "returns the number of DoH listeners" }, - { "getDOH3Frontend", true, "n", "returns the DoH3 frontend with index n" }, - { "getDOH3FrontendCount", true, "", "returns the number of DoH3 listeners" }, - { "getDOQFrontend", true, "n", "returns the DoQ frontend with index n" }, - { "getDOQFrontendCount", true, "", "returns the number of DoQ listeners" }, - { "getListOfAddressesOfNetworkInterface", true, "itf", "returns the list of addresses configured on a given network interface, as strings" }, - { "getListOfNetworkInterfaces", true, "", "returns the list of network interfaces present on the system, as strings" }, - { "getListOfRangesOfNetworkInterface", true, "itf", "returns the list of network ranges configured on a given network interface, as strings" }, - { "getMACAddress", true, "IP addr", "return the link-level address (MAC) corresponding to the supplied neighbour IP address, if known by the kernel" }, - { "getMetric", true, "name", "Get the value of a custom metric" }, - { "getOutgoingTLSSessionCacheSize", true, "", "returns the number of TLS sessions (for outgoing connections) currently cached" }, - { "getPool", true, "name", "return the pool named `name`, or \"\" for the default pool" }, - { "getPoolServers", true, "pool", "return servers part of this pool" }, - { "getPoolNames", true, "", "returns a table with all the pool names" }, - { "getQueryCounters", true, "[max=10]", "show current buffer of query counters, limited by 'max' if provided" }, - { "getResponseRing", true, "", "return the current content of the response ring" }, - { "getResponseRule", true, "selector", "Return the response rule corresponding to the selector, if any" }, - { "getRespRing", true, "", "return the qname/rcode content of the response ring" }, - { "getRule", true, "selector", "Return the rule corresponding to the selector, if any" }, - { "getSelfAnsweredResponseRule", true, "selector", "Return the self-answered response rule corresponding to the selector, if any" }, - { "getServer", true, "id", "returns server with index 'n' or whose uuid matches if 'id' is an UUID string" }, - { "getServers", true, "", "returns a table with all defined servers" }, - { "getStatisticsCounters", true, "", "returns a map of statistic counters" }, - { "getTopCacheHitResponseRules", true, "[top]", "return the `top` cache-hit response rules" }, - { "getTopCacheInsertedResponseRules", true, "[top]", "return the `top` cache-inserted response rules" }, - { "getTopResponseRules", true, "[top]", "return the `top` response rules" }, - { "getTopRules", true, "[top]", "return the `top` rules" }, - { "getTopSelfAnsweredResponseRules", true, "[top]", "return the `top` self-answered response rules" }, - { "getTLSContext", true, "n", "returns the TLS context with index n" }, - { "getTLSFrontend", true, "n", "returns the TLS frontend with index n" }, - { "getTLSFrontendCount", true, "", "returns the number of DoT listeners" }, - { "getVerbose", true, "", "get whether log messages at the verbose level will be logged" }, - { "grepq", true, R"(Netmask|DNS Name|100ms|{"::1", "powerdns.com", "100ms"} [, n] [,options])", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms" }, - { "hashPassword", true, "password [, workFactor]", "Returns a hashed and salted version of the supplied password, usable with 'setWebserverConfig()'"}, - { "HTTPHeaderRule", true, "name, regex", "matches DoH queries with a HTTP header 'name' whose content matches the regular expression 'regex'"}, - { "HTTPPathRegexRule", true, "regex", "matches DoH queries whose HTTP path matches 'regex'"}, - { "HTTPPathRule", true, "path", "matches DoH queries whose HTTP path is an exact match to 'path'"}, - { "HTTPStatusAction", true, "status, reason, body", "return an HTTP response"}, - { "inClientStartup", true, "", "returns true during console client parsing of configuration" }, - { "includeDirectory", true, "path", "include configuration files from `path`" }, - { "incMetric", true, "name", "Increment a custom metric" }, - { "KeyValueLookupKeyQName", true, "[wireFormat]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the qname of the query, either in wire format (default) or in plain text if 'wireFormat' is false" }, - { "KeyValueLookupKeySourceIP", true, "[v4Mask [, v6Mask [, includePort]]]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the (possibly bitmasked) source IP of the client in network byte-order." }, - { "KeyValueLookupKeySuffix", true, "[minLabels [,wireFormat]]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return a vector of keys based on the labels of the qname in DNS wire format or plain text" }, - { "KeyValueLookupKeyTag", true, "tag", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the value of the corresponding tag for this query, if it exists" }, - { "KeyValueStoreLookupAction", true, "kvs, lookupKey, destinationTag", "does a lookup into the key value store referenced by 'kvs' using the key returned by 'lookupKey', and storing the result if any into the tag named 'destinationTag'" }, - { "KeyValueStoreRangeLookupAction", true, "kvs, lookupKey, destinationTag", "does a range-based lookup into the key value store referenced by 'kvs' using the key returned by 'lookupKey', and storing the result if any into the tag named 'destinationTag'" }, - { "KeyValueStoreLookupRule", true, "kvs, lookupKey", "matches queries if the key is found in the specified Key Value store" }, - { "KeyValueStoreRangeLookupRule", true, "kvs, lookupKey", "matches queries if the key is found in the specified Key Value store" }, - { "leastOutstanding", false, "", "Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency"}, + {"addACL", true, "netmask", "add to the ACL set who can use this server"}, + {"addAction", true, R"(DNS rule, DNS action [, {uuid="UUID", name="name"}])", "add a rule"}, + {"addBPFFilterDynBlocks", true, "addresses, dynbpf[[, seconds=10], msg]", "This is the eBPF equivalent of addDynBlocks(), blocking a set of addresses for (optionally) a number of seconds, using an eBPF dynamic filter"}, + {"addCapabilitiesToRetain", true, "capability or list of capabilities", "Linux capabilities to retain after startup, like CAP_BPF"}, + {"addConsoleACL", true, "netmask", "add a netmask to the console ACL"}, + {"addDNSCryptBind", true, R"('127.0.0.1:8443", "provider name", "/path/to/resolver.cert", "/path/to/resolver.key", {reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}})", "listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of `provider name`, using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth optional parameter is a table of parameters"}, + {"addDOHLocal", true, "addr, certFile, keyFile [, urls [, vars]]", "listen to incoming DNS over HTTPS queries on the specified address using the specified certificate and key. The last two parameters are tables"}, + {"addDOH3Local", true, "addr, certFile, keyFile [, vars]", "listen to incoming DNS over HTTP/3 queries on the specified address using the specified certificate and key. The last parameter is a table"}, + {"addDOQLocal", true, "addr, certFile, keyFile [, vars]", "listen to incoming DNS over QUIC queries on the specified address using the specified certificate and key. The last parameter is a table"}, + {"addDynamicBlock", true, "address, message[, action [, seconds [, clientIPMask [, clientIPPortMask]]]]", "block the supplied address with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"}, + {"addDynBlocks", true, "addresses, message[, seconds[, action]]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"}, + {"addDynBlockSMT", true, "names, message[, seconds [, action]]", "block the set of names with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)"}, + {"addLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "add `addr` to the list of addresses we listen on"}, + {"addCacheHitResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache hit response rule"}, + {"addCacheInsertedResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a cache inserted response rule"}, + {"addMaintenanceCallback", true, "callback", "register a function to be called as part of the maintenance hook, every second"}, + {"addResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a response rule"}, + {"addSelfAnsweredResponseAction", true, R"(DNS rule, DNS response action [, {uuid="UUID", name="name"}}])", "add a self-answered response rule"}, + {"addTLSLocal", true, "addr, certFile(s), keyFile(s) [,params]", "listen to incoming DNS over TLS queries on the specified address using the specified certificate (or list of) and key (or list of). The last parameter is a table"}, + {"AllowAction", true, "", "let these packets go through"}, + {"AllowResponseAction", true, "", "let these packets go through"}, + {"AllRule", true, "", "matches all traffic"}, + {"AndRule", true, "list of DNS rules", "matches if all sub-rules matches"}, + {"benchRule", true, "DNS Rule [, iterations [, suffix]]", "bench the specified DNS rule"}, + {"carbonServer", true, "serverIP, [ourname], [interval]", "report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds"}, + {"clearConsoleHistory", true, "", "clear the internal (in-memory) history of console commands"}, + {"clearDynBlocks", true, "", "clear all dynamic blocks"}, + {"clearQueryCounters", true, "", "clears the query counter buffer"}, + {"clearRules", true, "", "remove all current rules"}, + {"controlSocket", true, "addr", "open a control socket on this address / connect to this address in client mode"}, + {"ContinueAction", true, "action", "execute the specified action and continue the processing of the remaining rules, regardless of the return of the action"}, + {"declareMetric", true, "name, type, description [, prometheusName]", "Declare a custom metric"}, + {"decMetric", true, "name", "Decrement a custom metric"}, + {"DelayAction", true, "milliseconds", "delay the response by the specified amount of milliseconds (UDP-only)"}, + {"DelayResponseAction", true, "milliseconds", "delay the response by the specified amount of milliseconds (UDP-only)"}, + {"delta", true, "", "shows all commands entered that changed the configuration"}, + {"DNSSECRule", true, "", "matches queries with the DO bit set"}, + {"DnstapLogAction", true, "identity, FrameStreamLogger [, alterFunction]", "send the contents of this query to a FrameStreamLogger or RemoteLogger as dnstap. `alterFunction` is a callback, receiving a DNSQuestion and a DnstapMessage, that can be used to modify the dnstap message"}, + {"DnstapLogResponseAction", true, "identity, FrameStreamLogger [, alterFunction]", "send the contents of this response to a remote or FrameStreamLogger or RemoteLogger as dnstap. `alterFunction` is a callback, receiving a DNSResponse and a DnstapMessage, that can be used to modify the dnstap message"}, + {"DropAction", true, "", "drop these packets"}, + {"DropResponseAction", true, "", "drop these packets"}, + {"DSTPortRule", true, "port", "matches questions received to the destination port specified"}, + {"dumpStats", true, "", "print all statistics we gather"}, + {"dynBlockRulesGroup", true, "", "return a new DynBlockRulesGroup object"}, + {"EDNSVersionRule", true, "version", "matches queries with the specified EDNS version"}, + {"EDNSOptionRule", true, "optcode", "matches queries with the specified EDNS0 option present"}, + {"ERCodeAction", true, "ercode", "Reply immediately by turning the query into a response with the specified EDNS extended rcode"}, + {"ERCodeRule", true, "rcode", "matches responses with the specified extended rcode (EDNS0)"}, + {"exceedNXDOMAINs", true, "rate, seconds", "get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds"}, + {"exceedQRate", true, "rate, seconds", "get set of address that exceed `rate` queries/s over `seconds` seconds"}, + {"exceedQTypeRate", true, "type, rate, seconds", "get set of address that exceed `rate` queries/s for queries of type `type` over `seconds` seconds"}, + {"exceedRespByterate", true, "rate, seconds", "get set of addresses that exceeded `rate` bytes/s answers over `seconds` seconds"}, + {"exceedServFails", true, "rate, seconds", "get set of addresses that exceed `rate` servfails/s over `seconds` seconds"}, + {"firstAvailable", false, "", "picks the server with the lowest `order` that has not exceeded its QPS limit"}, + {"fixupCase", true, "bool", "if set (default to no), rewrite the first qname of the question part of the answer to match the one from the query. It is only useful when you have a downstream server that messes up the case of the question qname in the answer"}, + {"generateDNSCryptCertificate", true, R"("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil)", "generate a new resolver private key and related certificate, valid from the `validFrom` timestamp until the `validUntil` one, signed with the provider private key"}, + {"generateDNSCryptProviderKeys", true, R"("/path/to/providerPublic.key", "/path/to/providerPrivate.key")", "generate a new provider keypair"}, + {"getAction", true, "n", "Returns the Action associated with rule n"}, + {"getBind", true, "n", "returns the listener at index n"}, + {"getBindCount", true, "", "returns the number of listeners all kinds"}, + {"getCacheHitResponseRule", true, "selector", "Return the cache-hit response rule corresponding to the selector, if any"}, + {"getCacheInsertedResponseRule", true, "selector", "Return the cache-inserted response rule corresponding to the selector, if any"}, + {"getCurrentTime", true, "", "returns the current time"}, + {"getDynamicBlocks", true, "", "returns a table of the current network-based dynamic blocks"}, + {"getDynamicBlocksSMT", true, "", "returns a table of the current suffix-based dynamic blocks"}, + {"getDNSCryptBind", true, "n", "return the `DNSCryptContext` object corresponding to the bind `n`"}, + {"getDNSCryptBindCount", true, "", "returns the number of DNSCrypt listeners"}, + {"getDOHFrontend", true, "n", "returns the DoH frontend with index n"}, + {"getDOHFrontendCount", true, "", "returns the number of DoH listeners"}, + {"getDOH3Frontend", true, "n", "returns the DoH3 frontend with index n"}, + {"getDOH3FrontendCount", true, "", "returns the number of DoH3 listeners"}, + {"getDOQFrontend", true, "n", "returns the DoQ frontend with index n"}, + {"getDOQFrontendCount", true, "", "returns the number of DoQ listeners"}, + {"getListOfAddressesOfNetworkInterface", true, "itf", "returns the list of addresses configured on a given network interface, as strings"}, + {"getListOfNetworkInterfaces", true, "", "returns the list of network interfaces present on the system, as strings"}, + {"getListOfRangesOfNetworkInterface", true, "itf", "returns the list of network ranges configured on a given network interface, as strings"}, + {"getMACAddress", true, "IP addr", "return the link-level address (MAC) corresponding to the supplied neighbour IP address, if known by the kernel"}, + {"getMetric", true, "name", "Get the value of a custom metric"}, + {"getOutgoingTLSSessionCacheSize", true, "", "returns the number of TLS sessions (for outgoing connections) currently cached"}, + {"getPool", true, "name", "return the pool named `name`, or \"\" for the default pool"}, + {"getPoolServers", true, "pool", "return servers part of this pool"}, + {"getPoolNames", true, "", "returns a table with all the pool names"}, + {"getQueryCounters", true, "[max=10]", "show current buffer of query counters, limited by 'max' if provided"}, + {"getResponseRing", true, "", "return the current content of the response ring"}, + {"getResponseRule", true, "selector", "Return the response rule corresponding to the selector, if any"}, + {"getRespRing", true, "", "return the qname/rcode content of the response ring"}, + {"getRule", true, "selector", "Return the rule corresponding to the selector, if any"}, + {"getSelfAnsweredResponseRule", true, "selector", "Return the self-answered response rule corresponding to the selector, if any"}, + {"getServer", true, "id", "returns server with index 'n' or whose uuid matches if 'id' is an UUID string"}, + {"getServers", true, "", "returns a table with all defined servers"}, + {"getStatisticsCounters", true, "", "returns a map of statistic counters"}, + {"getTopCacheHitResponseRules", true, "[top]", "return the `top` cache-hit response rules"}, + {"getTopCacheInsertedResponseRules", true, "[top]", "return the `top` cache-inserted response rules"}, + {"getTopResponseRules", true, "[top]", "return the `top` response rules"}, + {"getTopRules", true, "[top]", "return the `top` rules"}, + {"getTopSelfAnsweredResponseRules", true, "[top]", "return the `top` self-answered response rules"}, + {"getTLSContext", true, "n", "returns the TLS context with index n"}, + {"getTLSFrontend", true, "n", "returns the TLS frontend with index n"}, + {"getTLSFrontendCount", true, "", "returns the number of DoT listeners"}, + {"getVerbose", true, "", "get whether log messages at the verbose level will be logged"}, + {"grepq", true, R"(Netmask|DNS Name|100ms|{"::1", "powerdns.com", "100ms"} [, n] [,options])", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms"}, + {"hashPassword", true, "password [, workFactor]", "Returns a hashed and salted version of the supplied password, usable with 'setWebserverConfig()'"}, + {"HTTPHeaderRule", true, "name, regex", "matches DoH queries with a HTTP header 'name' whose content matches the regular expression 'regex'"}, + {"HTTPPathRegexRule", true, "regex", "matches DoH queries whose HTTP path matches 'regex'"}, + {"HTTPPathRule", true, "path", "matches DoH queries whose HTTP path is an exact match to 'path'"}, + {"HTTPStatusAction", true, "status, reason, body", "return an HTTP response"}, + {"inClientStartup", true, "", "returns true during console client parsing of configuration"}, + {"includeDirectory", true, "path", "include configuration files from `path`"}, + {"incMetric", true, "name", "Increment a custom metric"}, + {"KeyValueLookupKeyQName", true, "[wireFormat]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the qname of the query, either in wire format (default) or in plain text if 'wireFormat' is false"}, + {"KeyValueLookupKeySourceIP", true, "[v4Mask [, v6Mask [, includePort]]]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the (possibly bitmasked) source IP of the client in network byte-order."}, + {"KeyValueLookupKeySuffix", true, "[minLabels [,wireFormat]]", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return a vector of keys based on the labels of the qname in DNS wire format or plain text"}, + {"KeyValueLookupKeyTag", true, "tag", "Return a new KeyValueLookupKey object that, when passed to KeyValueStoreLookupAction or KeyValueStoreLookupRule, will return the value of the corresponding tag for this query, if it exists"}, + {"KeyValueStoreLookupAction", true, "kvs, lookupKey, destinationTag", "does a lookup into the key value store referenced by 'kvs' using the key returned by 'lookupKey', and storing the result if any into the tag named 'destinationTag'"}, + {"KeyValueStoreRangeLookupAction", true, "kvs, lookupKey, destinationTag", "does a range-based lookup into the key value store referenced by 'kvs' using the key returned by 'lookupKey', and storing the result if any into the tag named 'destinationTag'"}, + {"KeyValueStoreLookupRule", true, "kvs, lookupKey", "matches queries if the key is found in the specified Key Value store"}, + {"KeyValueStoreRangeLookupRule", true, "kvs, lookupKey", "matches queries if the key is found in the specified Key Value store"}, + {"leastOutstanding", false, "", "Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency"}, #if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS) - { "loadTLSEngine", true, "engineName [, defaultString]", "Load the OpenSSL engine named 'engineName', setting the engine default string to 'defaultString' if supplied"}, + {"loadTLSEngine", true, "engineName [, defaultString]", "Load the OpenSSL engine named 'engineName', setting the engine default string to 'defaultString' if supplied"}, #endif #if defined(HAVE_LIBSSL) && OPENSSL_VERSION_MAJOR >= 3 && defined(HAVE_TLS_PROVIDERS) - { "loadTLSProvider", true, "providerName", "Load the OpenSSL provider named 'providerName'"}, + {"loadTLSProvider", true, "providerName", "Load the OpenSSL provider named 'providerName'"}, #endif - { "LogAction", true, "[filename], [binary], [append], [buffered]", "Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form, the `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not." }, - { "LogResponseAction", true, "[filename], [append], [buffered]", "Log a line for each response, to the specified file if any, to the console (require verbose) otherwise. The `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not." }, - { "LuaAction", true, "function", "Invoke a Lua function that accepts a DNSQuestion" }, - { "LuaFFIAction", true, "function", "Invoke a Lua FFI function that accepts a DNSQuestion" }, - { "LuaFFIPerThreadAction", true, "function", "Invoke a Lua FFI function that accepts a DNSQuestion, with a per-thread Lua context" }, - { "LuaFFIPerThreadResponseAction", true, "function", "Invoke a Lua FFI function that accepts a DNSResponse, with a per-thread Lua context" }, - { "LuaFFIResponseAction", true, "function", "Invoke a Lua FFI function that accepts a DNSResponse" }, - { "LuaFFIRule", true, "function", "Invoke a Lua FFI function that filters DNS questions" }, - { "LuaResponseAction", true, "function", "Invoke a Lua function that accepts a DNSResponse" }, - { "LuaRule", true, "function", "Invoke a Lua function that filters DNS questions" }, + {"LogAction", true, "[filename], [binary], [append], [buffered]", "Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form, the `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not."}, + {"LogResponseAction", true, "[filename], [append], [buffered]", "Log a line for each response, to the specified file if any, to the console (require verbose) otherwise. The `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not."}, + {"LuaAction", true, "function", "Invoke a Lua function that accepts a DNSQuestion"}, + {"LuaFFIAction", true, "function", "Invoke a Lua FFI function that accepts a DNSQuestion"}, + {"LuaFFIPerThreadAction", true, "function", "Invoke a Lua FFI function that accepts a DNSQuestion, with a per-thread Lua context"}, + {"LuaFFIPerThreadResponseAction", true, "function", "Invoke a Lua FFI function that accepts a DNSResponse, with a per-thread Lua context"}, + {"LuaFFIResponseAction", true, "function", "Invoke a Lua FFI function that accepts a DNSResponse"}, + {"LuaFFIRule", true, "function", "Invoke a Lua FFI function that filters DNS questions"}, + {"LuaResponseAction", true, "function", "Invoke a Lua function that accepts a DNSResponse"}, + {"LuaRule", true, "function", "Invoke a Lua function that filters DNS questions"}, #ifdef HAVE_IPCIPHER - { "makeIPCipherKey", true, "password", "generates a 16-byte key that can be used to pseudonymize IP addresses with IP cipher" }, + {"makeIPCipherKey", true, "password", "generates a 16-byte key that can be used to pseudonymize IP addresses with IP cipher"}, #endif /* HAVE_IPCIPHER */ - { "makeKey", true, "", "generate a new server access key, emit configuration line ready for pasting" }, - { "makeRule", true, "rule", "Make a NetmaskGroupRule() or a SuffixMatchNodeRule(), depending on how it is called" } , - { "MaxQPSIPRule", true, "qps, [v4Mask=32 [, v6Mask=64 [, burst=qps [, expiration=300 [, cleanupDelay=60 [, scanFraction=10 [, shards=10]]]]]]]", "matches traffic exceeding the qps limit per subnet" }, - { "MaxQPSRule", true, "qps", "matches traffic **not** exceeding this qps limit" }, - { "mvCacheHitResponseRule", true, "from, to", "move cache hit response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" }, - { "mvCacheHitResponseRuleToTop", true, "", "move the last cache hit response rule to the first position" }, - { "mvCacheInsertedResponseRule", true, "from, to", "move cache inserted response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" }, - { "mvCacheInsertedResponseRuleToTop", true, "", "move the last cache inserted response rule to the first position" }, - { "mvResponseRule", true, "from, to", "move response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" }, - { "mvResponseRuleToTop", true, "", "move the last response rule to the first position" }, - { "mvRule", true, "from, to", "move rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule, in which case the rule will be moved to the last position" }, - { "mvRuleToTop", true, "", "move the last rule to the first position" }, - { "mvSelfAnsweredResponseRule", true, "from, to", "move self-answered response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule" }, - { "mvSelfAnsweredResponseRuleToTop", true, "", "move the last self-answered response rule to the first position" }, - { "NetmaskGroupRule", true, "nmg[, src]", "Matches traffic from/to the network range specified in nmg. Set the src parameter to false to match nmg against destination address instead of source address. This can be used to differentiate between clients" }, - { "newBPFFilter", true, "{ipv4MaxItems=int, ipv4PinnedPath=string, ipv6MaxItems=int, ipv6PinnedPath=string, cidr4MaxItems=int, cidr4PinnedPath=string, cidr6MaxItems=int, cidr6PinnedPath=string, qnamesMaxItems=int, qnamesPinnedPath=string, external=bool}", "Return a new eBPF socket filter with specified options." }, - { "newCA", true, "address", "Returns a ComboAddress based on `address`" }, + {"makeKey", true, "", "generate a new server access key, emit configuration line ready for pasting"}, + {"makeRule", true, "rule", "Make a NetmaskGroupRule() or a SuffixMatchNodeRule(), depending on how it is called"}, + {"MaxQPSIPRule", true, "qps, [v4Mask=32 [, v6Mask=64 [, burst=qps [, expiration=300 [, cleanupDelay=60 [, scanFraction=10 [, shards=10]]]]]]]", "matches traffic exceeding the qps limit per subnet"}, + {"MaxQPSRule", true, "qps", "matches traffic **not** exceeding this qps limit"}, + {"mvCacheHitResponseRule", true, "from, to", "move cache hit response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule"}, + {"mvCacheHitResponseRuleToTop", true, "", "move the last cache hit response rule to the first position"}, + {"mvCacheInsertedResponseRule", true, "from, to", "move cache inserted response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule"}, + {"mvCacheInsertedResponseRuleToTop", true, "", "move the last cache inserted response rule to the first position"}, + {"mvResponseRule", true, "from, to", "move response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule"}, + {"mvResponseRuleToTop", true, "", "move the last response rule to the first position"}, + {"mvRule", true, "from, to", "move rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule, in which case the rule will be moved to the last position"}, + {"mvRuleToTop", true, "", "move the last rule to the first position"}, + {"mvSelfAnsweredResponseRule", true, "from, to", "move self-answered response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule"}, + {"mvSelfAnsweredResponseRuleToTop", true, "", "move the last self-answered response rule to the first position"}, + {"NetmaskGroupRule", true, "nmg[, src]", "Matches traffic from/to the network range specified in nmg. Set the src parameter to false to match nmg against destination address instead of source address. This can be used to differentiate between clients"}, + {"newBPFFilter", true, "{ipv4MaxItems=int, ipv4PinnedPath=string, ipv6MaxItems=int, ipv6PinnedPath=string, cidr4MaxItems=int, cidr4PinnedPath=string, cidr6MaxItems=int, cidr6PinnedPath=string, qnamesMaxItems=int, qnamesPinnedPath=string, external=bool}", "Return a new eBPF socket filter with specified options."}, + {"newCA", true, "address", "Returns a ComboAddress based on `address`"}, #ifdef HAVE_CDB - { "newCDBKVStore", true, "fname, refreshDelay", "Return a new KeyValueStore object associated to the corresponding CDB database" }, + {"newCDBKVStore", true, "fname, refreshDelay", "Return a new KeyValueStore object associated to the corresponding CDB database"}, #endif - { "newDNSName", true, "name", "make a DNSName based on this .-terminated name" }, - { "newDNSNameSet", true, "", "returns a new DNSNameSet" }, - { "newDynBPFFilter", true, "bpf", "Return a new dynamic eBPF filter associated to a given BPF Filter" }, - { "newFrameStreamTcpLogger", true, "addr [, options]", "create a FrameStream logger object writing to a TCP address (addr should be ip:port), to use with `DnstapLogAction()` and `DnstapLogResponseAction()`" }, - { "newFrameStreamUnixLogger", true, "socket [, options]", "create a FrameStream logger object writing to a local unix socket, to use with `DnstapLogAction()` and `DnstapLogResponseAction()`" }, + {"newDNSName", true, "name", "make a DNSName based on this .-terminated name"}, + {"newDNSNameSet", true, "", "returns a new DNSNameSet"}, + {"newDynBPFFilter", true, "bpf", "Return a new dynamic eBPF filter associated to a given BPF Filter"}, + {"newFrameStreamTcpLogger", true, "addr [, options]", "create a FrameStream logger object writing to a TCP address (addr should be ip:port), to use with `DnstapLogAction()` and `DnstapLogResponseAction()`"}, + {"newFrameStreamUnixLogger", true, "socket [, options]", "create a FrameStream logger object writing to a local unix socket, to use with `DnstapLogAction()` and `DnstapLogResponseAction()`"}, #ifdef HAVE_LMDB - { "newLMDBKVStore", true, "fname, dbName [, noLock]", "Return a new KeyValueStore object associated to the corresponding LMDB database" }, + {"newLMDBKVStore", true, "fname, dbName [, noLock]", "Return a new KeyValueStore object associated to the corresponding LMDB database"}, #endif - { "newNMG", true, "", "Returns a NetmaskGroup" }, - { "newPacketCache", true, "maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, options={}]", "return a new Packet Cache" }, - { "newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity" }, - { "newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`" }, - { "newRuleAction", true, R"(DNS rule, DNS action [, {uuid="UUID", name="name"}])", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" }, - { "newServer", true, R"({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName="a.root-servers.net.", checkType="A", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface", sockets=1, reconnectOnUp=false})", "instantiate a server" }, - { "newServerPolicy", true, "name, function", "create a policy object from a Lua function" }, - { "newSuffixMatchNode", true, "", "returns a new SuffixMatchNode" }, - { "newSVCRecordParameters", true, "priority, target, mandatoryParams, alpns, noDefaultAlpn [, port [, ech [, ipv4hints [, ipv6hints [, additionalParameters ]]]]]", "return a new SVCRecordParameters object, to use with SpoofSVCAction" }, - { "NegativeAndSOAAction", true, "nxd, zone, ttl, mname, rname, serial, refresh, retry, expire, minimum [, options]", "Turn a query into a NXDomain or NoData answer and sets a SOA record in the additional section" }, - { "NoneAction", true, "", "Does nothing. Subsequent rules are processed after this action" }, - { "NotRule", true, "selector", "Matches the traffic if the selector rule does not match" }, - { "OpcodeRule", true, "code", "Matches queries with opcode code. code can be directly specified as an integer, or one of the built-in DNSOpcodes" }, - { "OrRule", true, "selectors", "Matches the traffic if one or more of the the selectors rules does match" }, - { "PoolAction", true, "poolname [, stop]", "set the packet into the specified pool" }, - { "PoolAvailableRule", true, "poolname", "Check whether a pool has any servers available to handle queries" }, - { "PoolOutstandingRule", true, "poolname, limit", "Check whether a pool has outstanding queries above limit" }, - { "printDNSCryptProviderFingerprint", true, R"("/path/to/providerPublic.key")", "display the fingerprint of the provided resolver public key" }, - { "ProbaRule", true, "probability", "Matches queries with a given probability. 1.0 means always" }, - { "ProxyProtocolValueRule", true, "type [, value]", "matches queries with a specified Proxy Protocol TLV value of that type, optionally matching the content of the option as well" }, - { "QClassRule", true, "qclass", "Matches queries with the specified qclass. class can be specified as an integer or as one of the built-in DNSClass" }, - { "QNameLabelsCountRule", true, "min, max", "matches if the qname has less than `min` or more than `max` labels" }, - { "QNameRule", true, "qname", "matches queries with the specified qname" }, - { "QNameSetRule", true, "set", "Matches if the set contains exact qname" }, - { "QNameWireLengthRule", true, "min, max", "matches if the qname's length on the wire is less than `min` or more than `max` bytes" }, - { "QPSAction", true, "maxqps", "Drop a packet if it does exceed the maxqps queries per second limits. Letting the subsequent rules apply otherwise" }, - { "QPSPoolAction", true, "maxqps, poolname [, stop]", "Send the packet into the specified pool only if it does not exceed the maxqps queries per second limits. Letting the subsequent rules apply otherwise" }, - { "QTypeRule", true, "qtype", "matches queries with the specified qtype" }, - { "RCodeAction", true, "rcode", "Reply immediately by turning the query into a response with the specified rcode" }, - { "RCodeRule", true, "rcode", "matches responses with the specified rcode" }, - { "RDRule", true, "", "Matches queries with the RD flag set" }, - { "RecordsCountRule", true, "section, minCount, maxCount", "Matches if there is at least minCount and at most maxCount records in the section section. section can be specified as an integer or as a DNS Packet Sections" }, - { "RecordsTypeCountRule", true, "section, qtype, minCount, maxCount", "Matches if there is at least minCount and at most maxCount records of type type in the section section" }, - { "RegexRule", true, "regex", "matches the query name against the supplied regex" }, - { "registerDynBPFFilter", true, "DynBPFFilter", "register this dynamic BPF filter into the web interface so that its counters are displayed" }, - { "reloadAllCertificates", true, "", "reload all DNSCrypt and TLS certificates, along with their associated keys" }, - { "RemoteLogAction", true, "RemoteLogger [, alterFunction [, serverID]]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes. `serverID` is the server identifier." }, - { "RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME [, serverID]]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records. `serverID` is the server identifier." }, - { "requestTCPStatesDump", true, "", "Request a dump of the TCP states (incoming connections, outgoing connections) during the next scan. Useful for debugging purposes only" }, - { "rmACL", true, "netmask", "remove netmask from ACL" }, - { "rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" }, - { "rmCacheInsertedResponseRule", true, "id", "remove cache inserted response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" }, - { "rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" }, - { "rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" }, - { "rmSelfAnsweredResponseRule", true, "id", "remove self-answered response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID" }, - { "rmServer", true, "id", "remove server with index 'id' or whose uuid matches if 'id' is an UUID string" }, - { "roundrobin", false, "", "Simple round robin over available servers" }, - { "sendCustomTrap", true, "str", "send a custom `SNMP` trap from Lua, containing the `str` string"}, - { "setACL", true, "{netmask, netmask}", "replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us" }, - { "setACLFromFile", true, "file", "replace the ACL set with netmasks in this file" }, - { "setAddEDNSToSelfGeneratedResponses", true, "add", "set whether to add EDNS to self-generated responses, provided that the initial query had EDNS" }, - { "setAllowEmptyResponse", true, "allow", "Set to true (defaults to false) to allow empty responses (qdcount=0) with a NoError or NXDomain rcode (default) from backends" }, - { "setAPIWritable", true, "bool, dir", "allow modifications via the API. if `dir` is set, it must be a valid directory where the configuration files will be written by the API" }, - { "setCacheCleaningDelay", true, "num", "Set the interval in seconds between two runs of the cache cleaning algorithm, removing expired entries" }, - { "setCacheCleaningPercentage", true, "num", "Set the percentage of the cache that the cache cleaning algorithm will try to free by removing expired entries. By default (100), all expired entries are remove" }, - { "setConsistentHashingBalancingFactor", true, "factor", "Set the balancing factor for bounded-load consistent hashing" }, - { "setConsoleACL", true, "{netmask, netmask}", "replace the console ACL set with these netmasks" }, - { "setConsoleConnectionsLogging", true, "enabled", "whether to log the opening and closing of console connections" }, - { "setConsoleMaximumConcurrentConnections", true, "max", "Set the maximum number of concurrent console connections" }, - { "setConsoleOutputMaxMsgSize", true, "messageSize", "set console message maximum size in bytes, default is 10 MB" }, - { "setDefaultBPFFilter", true, "filter", "When used at configuration time, the corresponding BPFFilter will be attached to every bind" }, - { "setDoHDownstreamCleanupInterval", true, "interval", "minimum interval in seconds between two cleanups of the idle DoH downstream connections" }, - { "setDoHDownstreamMaxIdleTime", true, "time", "Maximum time in seconds that a downstream DoH connection to a backend might stay idle" }, - { "setDynBlocksAction", true, "action", "set which action is performed when a query is blocked. Only DNSAction.Drop (the default) and DNSAction.Refused are supported" }, - { "setDynBlocksPurgeInterval", true, "sec", "set how often the expired dynamic block entries should be removed" }, - { "setDropEmptyQueries", true, "drop", "Whether to drop empty queries right away instead of sending a NOTIMP response" }, - { "setECSOverride", true, "bool", "whether to override an existing EDNS Client Subnet value in the query" }, - { "setECSSourcePrefixV4", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv4 queries" }, - { "setECSSourcePrefixV6", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv6 queries" }, - { "setKey", true, "key", "set access key to that key" }, - { "setLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "reset the list of addresses we listen on to this address" }, - { "setMaxCachedDoHConnectionsPerDownstream", true, "max", "Set the maximum number of inactive DoH connections to a backend cached by each worker DoH thread" }, - { "setMaxCachedTCPConnectionsPerDownstream", true, "max", "Set the maximum number of inactive TCP connections to a backend cached by each worker TCP thread" }, - { "setMaxTCPClientThreads", true, "n", "set the maximum of TCP client threads, handling TCP connections" }, - { "setMaxTCPConnectionDuration", true, "n", "set the maximum duration of an incoming TCP connection, in seconds. 0 means unlimited" }, - { "setMaxTCPConnectionsPerClient", true, "n", "set the maximum number of TCP connections per client. 0 means unlimited" }, - { "setMaxTCPQueriesPerConnection", true, "n", "set the maximum number of queries in an incoming TCP connection. 0 means unlimited" }, - { "setMaxTCPQueuedConnections", true, "n", "set the maximum number of TCP connections queued (waiting to be picked up by a client thread)" }, - { "setMaxUDPOutstanding", true, "n", "set the maximum number of outstanding UDP queries to a given backend server. This can only be set at configuration time and defaults to 65535" }, - { "setMetric", true, "name, value", "Set the value of a custom metric to the supplied value" }, - { "setPayloadSizeOnSelfGeneratedAnswers", true, "payloadSize", "set the UDP payload size advertised via EDNS on self-generated responses" }, - { "setPoolServerPolicy", true, "policy, pool", "set the server selection policy for this pool to that policy" }, - { "setPoolServerPolicyLua", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'" }, - { "setPoolServerPolicyLuaFFI", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'" }, - { "setPoolServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy for this pool to one named 'name' and returned by the Lua FFI code passed in 'code'" }, - { "setProxyProtocolACL", true, "{netmask, netmask}", "Set the netmasks who are allowed to send Proxy Protocol headers in front of queries/connections" }, - { "setProxyProtocolApplyACLToProxiedClients", true, "apply", "Whether the general ACL should be applied to the source IP address gathered from a Proxy Protocol header, in addition to being first applied to the source address seen by dnsdist" }, - { "setProxyProtocolMaximumPayloadSize", true, "max", "Set the maximum size of a Proxy Protocol payload, in bytes" }, - { "setQueryCount", true, "bool", "set whether queries should be counted" }, - { "setQueryCountFilter", true, "func", "filter queries that would be counted, where `func` is a function with parameter `dq` which decides whether a query should and how it should be counted" }, - { "SetReducedTTLResponseAction", true, "percentage", "Reduce the TTL of records in a response to a given percentage" }, - { "setRingBuffersLockRetries", true, "n", "set the number of attempts to get a non-blocking lock to a ringbuffer shard before blocking" }, - { "setRingBuffersOptions", true, "{ lockRetries=int, recordQueries=true, recordResponses=true }", "set ringbuffer options" }, - { "setRingBuffersSize", true, "n [, numberOfShards]", "set the capacity of the ringbuffers used for live traffic inspection to `n`, and optionally the number of shards to use to `numberOfShards`" }, - { "setRoundRobinFailOnNoServer", true, "value", "By default the roundrobin load-balancing policy will still try to select a backend even if all backends are currently down. Setting this to true will make the policy fail and return that no server is available instead" }, - { "setRules", true, "list of rules", "replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see `newRuleAction()`)" }, - { "setSecurityPollInterval", true, "n", "set the security polling interval to `n` seconds" }, - { "setSecurityPollSuffix", true, "suffix", "set the security polling suffix to the specified value" }, - { "setServerPolicy", true, "policy", "set server selection policy to that policy" }, - { "setServerPolicyLua", true, "name, function", "set server selection policy to one named 'name' and provided by 'function'" }, - { "setServerPolicyLuaFFI", true, "name, function", "set server selection policy to one named 'name' and provided by the Lua FFI 'function'" }, - { "setServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy to one named 'name' and returned by the Lua FFI code passed in 'code'" }, - { "setServFailWhenNoServer", true, "bool", "if set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query" }, - { "setStaleCacheEntriesTTL", true, "n", "allows using cache entries expired for at most n seconds when there is no backend available to answer for a query" }, - { "setStructuredLogging", true, "value [, options]", "set whether log messages should be in structured-logging-like format" }, - { "setSyslogFacility", true, "facility", "set the syslog logging facility to 'facility'. Defaults to LOG_DAEMON" }, - { "setTCPDownstreamCleanupInterval", true, "interval", "minimum interval in seconds between two cleanups of the idle TCP downstream connections" }, - { "setTCPFastOpenKey", true, "string", "TCP Fast Open Key" }, - { "setTCPDownstreamMaxIdleTime", true, "time", "Maximum time in seconds that a downstream TCP connection to a backend might stay idle" }, - { "setTCPInternalPipeBufferSize", true, "size", "Set the size in bytes of the internal buffer of the pipes used internally to distribute connections to TCP (and DoT) workers threads" }, - { "setTCPRecvTimeout", true, "n", "set the read timeout on TCP connections from the client, in seconds" }, - { "setTCPSendTimeout", true, "n", "set the write timeout on TCP connections from the client, in seconds" }, - { "setUDPMultipleMessagesVectorSize", true, "n", "set the size of the vector passed to recvmmsg() to receive UDP messages. Default to 1 which means that the feature is disabled and recvmsg() is used instead" }, - { "setUDPSocketBufferSizes", true, "recv, send", "Set the size of the receive (SO_RCVBUF) and send (SO_SNDBUF) buffers for incoming UDP sockets" }, - { "setUDPTimeout", true, "n", "set the maximum time dnsdist will wait for a response from a backend over UDP, in seconds" }, - { "setVerbose", true, "bool", "set whether log messages at the verbose level will be logged" }, - { "setVerboseHealthChecks", true, "bool", "set whether health check errors will be logged" }, - { "setVerboseLogDestination", true, "destination file", "Set a destination file to write the 'verbose' log messages to, instead of sending them to syslog and/or the standard output" }, - { "setWebserverConfig", true, "[{password=string, apiKey=string, customHeaders, statsRequireAuthentication}]", "Updates webserver configuration" }, - { "setWeightedBalancingFactor", true, "factor", "Set the balancing factor for bounded-load weighted policies (whashed, wrandom)" }, - { "setWHashedPertubation", true, "value", "Set the hash perturbation value to be used in the whashed policy instead of a random one, allowing to have consistent whashed results on different instance" }, - { "show", true, "string", "outputs `string`" }, - { "showACL", true, "", "show our ACL set" }, - { "showBinds", true, "", "show listening addresses (frontends)" }, - { "showCacheHitResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined cache hit response rules, optionally with their UUIDs and optionally truncated to a given width" }, - { "showConsoleACL", true, "", "show our current console ACL set" }, - { "showDNSCryptBinds", true, "", "display the currently configured DNSCrypt binds" }, - { "showDOHFrontends", true, "", "list all the available DOH frontends" }, - { "showDOH3Frontends", true, "", "list all the available DOH3 frontends" }, - { "showDOHResponseCodes", true, "", "show the HTTP response code statistics for the DoH frontends"}, - { "showDOQFrontends", true, "", "list all the available DOQ frontends" }, - { "showDynBlocks", true, "", "show dynamic blocks in force" }, - { "showPools", true, "", "show the available pools" }, - { "showPoolServerPolicy", true, "pool", "show server selection policy for this pool" }, - { "showResponseLatency", true, "", "show a plot of the response time latency distribution" }, - { "showResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined response rules, optionally with their UUIDs and optionally truncated to a given width" }, - { "showRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined rules, optionally with their UUIDs and optionally truncated to a given width" }, - { "showSecurityStatus", true, "", "Show the security status"}, - { "showSelfAnsweredResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined self-answered response rules, optionally with their UUIDs and optionally truncated to a given width" }, - { "showServerPolicy", true, "", "show name of currently operational server selection policy" }, - { "showServers", true, "[{showUUIDs=false}]", "output all servers, optionally with their UUIDs" }, - { "showTCPStats", true, "", "show some statistics regarding TCP" }, - { "showTLSContexts", true, "", "list all the available TLS contexts" }, - { "showTLSErrorCounters", true, "", "show metrics about TLS handshake failures" }, - { "showVersion", true, "", "show the current version" }, - { "showWebserverConfig", true, "", "Show the current webserver configuration" }, - { "shutdown", true, "", "shut down `dnsdist`" }, - { "snmpAgent", true, "enableTraps [, daemonSocket]", "enable `SNMP` support. `enableTraps` is a boolean indicating whether traps should be sent and `daemonSocket` an optional string specifying how to connect to the daemon agent"}, - { "SetAdditionalProxyProtocolValueAction", true, "type, value", "Add a Proxy Protocol TLV value of this type" }, - { "SetDisableECSAction", true, "", "Disable the sending of ECS to the backend. Subsequent rules are processed after this action." }, - { "SetDisableValidationAction", true, "", "set the CD bit in the question, let it go through" }, - { "SetECSAction", true, "v4[, v6]", "Set the ECS prefix and prefix length sent to backends to an arbitrary value" }, - { "SetECSOverrideAction", true, "override", "Whether an existing EDNS Client Subnet value should be overridden (true) or not (false). Subsequent rules are processed after this action" }, - { "SetECSPrefixLengthAction", true, "v4, v6", "Set the ECS prefix length. Subsequent rules are processed after this action" }, - { "SetMacAddrAction", true, "option", "Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this action" }, - { "SetEDNSOptionAction", true, "option, data", "Add arbitrary EDNS option and data to the query. Subsequent rules are processed after this action" }, - { "SetExtendedDNSErrorAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action" }, - { "SetExtendedDNSErrorResponseAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to this response. Subsequent rules are processed after this action" }, - { "SetNoRecurseAction", true, "", "strip RD bit from the question, let it go through" }, - { "setOutgoingDoHWorkerThreads", true, "n", "Number of outgoing DoH worker threads" }, - { "SetProxyProtocolValuesAction", true, "values", "Set the Proxy-Protocol values for this queries to 'values'" }, - { "SetSkipCacheAction", true, "", "Don’t lookup the cache for this query, don’t store the answer" }, - { "SetSkipCacheResponseAction", true, "", "Don’t store this response into the cache" }, - { "SetTagAction", true, "name, value", "set the tag named 'name' to the given value" }, - { "SetTagResponseAction", true, "name, value", "set the tag named 'name' to the given value" }, - { "SetTempFailureCacheTTLAction", true, "ttl", "set packetcache TTL for temporary failure replies" }, - { "SNIRule", true, "name", "Create a rule which matches on the incoming TLS SNI value, if any (DoT or DoH)" }, - { "SNMPTrapAction", true, "[reason]", "send an SNMP trap, adding the optional `reason` string as the query description"}, - { "SNMPTrapResponseAction", true, "[reason]", "send an SNMP trap, adding the optional `reason` string as the response description"}, - { "SpoofAction", true, "ip|list of ips [, options]", "forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA). If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in" }, - { "SpoofCNAMEAction", true, "cname [, options]", "Forge a response with the specified CNAME value" }, - { "SpoofRawAction", true, "raw|list of raws [, options]", "Forge a response with the specified record data as raw bytes. If you specify multiple raws (it is assumed they match the query type), all will get spoofed in" }, - { "SpoofSVCAction", true, "list of svcParams [, options]", "Forge a response with the specified SVC record data" } , - { "SuffixMatchNodeRule", true, "smn[, quiet]", "Matches based on a group of domain suffixes for rapid testing of membership. Pass true as second parameter to prevent listing of all domains matched" }, - { "TagRule", true, "name [, value]", "matches if the tag named 'name' is present, with the given 'value' matching if any" }, - { "TCAction", true, "", "create answer to query with TC and RD bits set, to move to TCP" }, - { "TCPRule", true, "[tcp]", "Matches question received over TCP if tcp is true, over UDP otherwise" }, - { "TCResponseAction", true, "", "truncate a response" }, - { "TeeAction", true, "remote [, addECS [, local]]", "send copy of query to remote, optionally adding ECS info, optionally set local address" }, - { "testCrypto", true, "", "test of the crypto all works" }, - { "TimedIPSetRule", true, "", "Create a rule which matches a set of IP addresses which expire"}, - { "topBandwidth", true, "top", "show top-`top` clients that consume the most bandwidth over length of ringbuffer" }, - { "topCacheHitResponseRules", true, "[top][, vars]", "show `top` cache-hit response rules" }, - { "topCacheInsertedResponseRules", true, "[top][, vars]", "show `top` cache-inserted response rules" }, - { "topClients", true, "n", "show top-`n` clients sending the most queries over length of ringbuffer" }, - { "topQueries", true, "n[, labels]", "show top 'n' queries, as grouped when optionally cut down to 'labels' labels" }, - { "topResponses", true, "n, kind[, labels]", "show top 'n' responses with RCODE=kind (0=NO Error, 2=ServFail, 3=NXDomain), as grouped when optionally cut down to 'labels' labels" }, - { "topResponseRules", true, "[top][, vars]", "show `top` response rules" }, - { "topRules", true, "[top][, vars]", "show `top` rules" }, - { "topSelfAnsweredResponseRules", true, "[top][, vars]", "show `top` self-answered response rules" }, - { "topSlow", true, "[top][, limit][, labels]", "show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels" }, - { "TrailingDataRule", true, "", "Matches if the query has trailing data" }, - { "truncateTC", true, "bool", "if set (defaults to no starting with dnsdist 1.2.0) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22. Note: turning this on breaks compatibility with RFC 6891." }, - { "unregisterDynBPFFilter", true, "DynBPFFilter", "unregister this dynamic BPF filter" }, - { "webserver", true, "address:port", "launch a webserver with stats on that address" }, - { "whashed", false, "", "Weighted hashed ('sticky') distribution over available servers, based on the server 'weight' parameter" }, - { "chashed", false, "", "Consistent hashed ('sticky') distribution over available servers, also based on the server 'weight' parameter" }, - { "wrandom", false, "", "Weighted random over available servers, based on the server 'weight' parameter" }, + {"newNMG", true, "", "Returns a NetmaskGroup"}, + {"newPacketCache", true, "maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, options={}]", "return a new Packet Cache"}, + {"newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity"}, + {"newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`"}, + {"newRuleAction", true, R"(DNS rule, DNS action [, {uuid="UUID", name="name"}])", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`"}, + {"newServer", true, R"({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName="a.root-servers.net.", checkType="A", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface", sockets=1, reconnectOnUp=false})", "instantiate a server"}, + {"newServerPolicy", true, "name, function", "create a policy object from a Lua function"}, + {"newSuffixMatchNode", true, "", "returns a new SuffixMatchNode"}, + {"newSVCRecordParameters", true, "priority, target, mandatoryParams, alpns, noDefaultAlpn [, port [, ech [, ipv4hints [, ipv6hints [, additionalParameters ]]]]]", "return a new SVCRecordParameters object, to use with SpoofSVCAction"}, + {"NegativeAndSOAAction", true, "nxd, zone, ttl, mname, rname, serial, refresh, retry, expire, minimum [, options]", "Turn a query into a NXDomain or NoData answer and sets a SOA record in the additional section"}, + {"NoneAction", true, "", "Does nothing. Subsequent rules are processed after this action"}, + {"NotRule", true, "selector", "Matches the traffic if the selector rule does not match"}, + {"OpcodeRule", true, "code", "Matches queries with opcode code. code can be directly specified as an integer, or one of the built-in DNSOpcodes"}, + {"OrRule", true, "selectors", "Matches the traffic if one or more of the the selectors rules does match"}, + {"PoolAction", true, "poolname [, stop]", "set the packet into the specified pool"}, + {"PoolAvailableRule", true, "poolname", "Check whether a pool has any servers available to handle queries"}, + {"PoolOutstandingRule", true, "poolname, limit", "Check whether a pool has outstanding queries above limit"}, + {"printDNSCryptProviderFingerprint", true, R"("/path/to/providerPublic.key")", "display the fingerprint of the provided resolver public key"}, + {"ProbaRule", true, "probability", "Matches queries with a given probability. 1.0 means always"}, + {"ProxyProtocolValueRule", true, "type [, value]", "matches queries with a specified Proxy Protocol TLV value of that type, optionally matching the content of the option as well"}, + {"QClassRule", true, "qclass", "Matches queries with the specified qclass. class can be specified as an integer or as one of the built-in DNSClass"}, + {"QNameLabelsCountRule", true, "min, max", "matches if the qname has less than `min` or more than `max` labels"}, + {"QNameRule", true, "qname", "matches queries with the specified qname"}, + {"QNameSetRule", true, "set", "Matches if the set contains exact qname"}, + {"QNameWireLengthRule", true, "min, max", "matches if the qname's length on the wire is less than `min` or more than `max` bytes"}, + {"QPSAction", true, "maxqps", "Drop a packet if it does exceed the maxqps queries per second limits. Letting the subsequent rules apply otherwise"}, + {"QPSPoolAction", true, "maxqps, poolname [, stop]", "Send the packet into the specified pool only if it does not exceed the maxqps queries per second limits. Letting the subsequent rules apply otherwise"}, + {"QTypeRule", true, "qtype", "matches queries with the specified qtype"}, + {"RCodeAction", true, "rcode", "Reply immediately by turning the query into a response with the specified rcode"}, + {"RCodeRule", true, "rcode", "matches responses with the specified rcode"}, + {"RDRule", true, "", "Matches queries with the RD flag set"}, + {"RecordsCountRule", true, "section, minCount, maxCount", "Matches if there is at least minCount and at most maxCount records in the section section. section can be specified as an integer or as a DNS Packet Sections"}, + {"RecordsTypeCountRule", true, "section, qtype, minCount, maxCount", "Matches if there is at least minCount and at most maxCount records of type type in the section section"}, + {"RegexRule", true, "regex", "matches the query name against the supplied regex"}, + {"registerDynBPFFilter", true, "DynBPFFilter", "register this dynamic BPF filter into the web interface so that its counters are displayed"}, + {"reloadAllCertificates", true, "", "reload all DNSCrypt and TLS certificates, along with their associated keys"}, + {"RemoteLogAction", true, "RemoteLogger [, alterFunction [, serverID]]", "send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes. `serverID` is the server identifier."}, + {"RemoteLogResponseAction", true, "RemoteLogger [,alterFunction [,includeCNAME [, serverID]]]", "send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records. `serverID` is the server identifier."}, + {"requestTCPStatesDump", true, "", "Request a dump of the TCP states (incoming connections, outgoing connections) during the next scan. Useful for debugging purposes only"}, + {"rmACL", true, "netmask", "remove netmask from ACL"}, + {"rmCacheHitResponseRule", true, "id", "remove cache hit response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID"}, + {"rmCacheInsertedResponseRule", true, "id", "remove cache inserted response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID"}, + {"rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID"}, + {"rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID"}, + {"rmSelfAnsweredResponseRule", true, "id", "remove self-answered response rule in position 'id', or whose uuid matches if 'id' is an UUID string, or finally whose name matches if 'id' is a string but not a valid UUID"}, + {"rmServer", true, "id", "remove server with index 'id' or whose uuid matches if 'id' is an UUID string"}, + {"roundrobin", false, "", "Simple round robin over available servers"}, + {"sendCustomTrap", true, "str", "send a custom `SNMP` trap from Lua, containing the `str` string"}, + {"setACL", true, "{netmask, netmask}", "replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us"}, + {"setACLFromFile", true, "file", "replace the ACL set with netmasks in this file"}, + {"setAddEDNSToSelfGeneratedResponses", true, "add", "set whether to add EDNS to self-generated responses, provided that the initial query had EDNS"}, + {"setAllowEmptyResponse", true, "allow", "Set to true (defaults to false) to allow empty responses (qdcount=0) with a NoError or NXDomain rcode (default) from backends"}, + {"setAPIWritable", true, "bool, dir", "allow modifications via the API. if `dir` is set, it must be a valid directory where the configuration files will be written by the API"}, + {"setCacheCleaningDelay", true, "num", "Set the interval in seconds between two runs of the cache cleaning algorithm, removing expired entries"}, + {"setCacheCleaningPercentage", true, "num", "Set the percentage of the cache that the cache cleaning algorithm will try to free by removing expired entries. By default (100), all expired entries are remove"}, + {"setConsistentHashingBalancingFactor", true, "factor", "Set the balancing factor for bounded-load consistent hashing"}, + {"setConsoleACL", true, "{netmask, netmask}", "replace the console ACL set with these netmasks"}, + {"setConsoleConnectionsLogging", true, "enabled", "whether to log the opening and closing of console connections"}, + {"setConsoleMaximumConcurrentConnections", true, "max", "Set the maximum number of concurrent console connections"}, + {"setConsoleOutputMaxMsgSize", true, "messageSize", "set console message maximum size in bytes, default is 10 MB"}, + {"setDefaultBPFFilter", true, "filter", "When used at configuration time, the corresponding BPFFilter will be attached to every bind"}, + {"setDoHDownstreamCleanupInterval", true, "interval", "minimum interval in seconds between two cleanups of the idle DoH downstream connections"}, + {"setDoHDownstreamMaxIdleTime", true, "time", "Maximum time in seconds that a downstream DoH connection to a backend might stay idle"}, + {"setDynBlocksAction", true, "action", "set which action is performed when a query is blocked. Only DNSAction.Drop (the default) and DNSAction.Refused are supported"}, + {"setDynBlocksPurgeInterval", true, "sec", "set how often the expired dynamic block entries should be removed"}, + {"setDropEmptyQueries", true, "drop", "Whether to drop empty queries right away instead of sending a NOTIMP response"}, + {"setECSOverride", true, "bool", "whether to override an existing EDNS Client Subnet value in the query"}, + {"setECSSourcePrefixV4", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv4 queries"}, + {"setECSSourcePrefixV6", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv6 queries"}, + {"setKey", true, "key", "set access key to that key"}, + {"setLocal", true, R"(addr [, {doTCP=true, reusePort=false, tcpFastOpenQueueSize=0, interface="", cpus={}}])", "reset the list of addresses we listen on to this address"}, + {"setMaxCachedDoHConnectionsPerDownstream", true, "max", "Set the maximum number of inactive DoH connections to a backend cached by each worker DoH thread"}, + {"setMaxCachedTCPConnectionsPerDownstream", true, "max", "Set the maximum number of inactive TCP connections to a backend cached by each worker TCP thread"}, + {"setMaxTCPClientThreads", true, "n", "set the maximum of TCP client threads, handling TCP connections"}, + {"setMaxTCPConnectionDuration", true, "n", "set the maximum duration of an incoming TCP connection, in seconds. 0 means unlimited"}, + {"setMaxTCPConnectionsPerClient", true, "n", "set the maximum number of TCP connections per client. 0 means unlimited"}, + {"setMaxTCPQueriesPerConnection", true, "n", "set the maximum number of queries in an incoming TCP connection. 0 means unlimited"}, + {"setMaxTCPQueuedConnections", true, "n", "set the maximum number of TCP connections queued (waiting to be picked up by a client thread)"}, + {"setMaxUDPOutstanding", true, "n", "set the maximum number of outstanding UDP queries to a given backend server. This can only be set at configuration time and defaults to 65535"}, + {"setMetric", true, "name, value", "Set the value of a custom metric to the supplied value"}, + {"setPayloadSizeOnSelfGeneratedAnswers", true, "payloadSize", "set the UDP payload size advertised via EDNS on self-generated responses"}, + {"setPoolServerPolicy", true, "policy, pool", "set the server selection policy for this pool to that policy"}, + {"setPoolServerPolicyLua", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'"}, + {"setPoolServerPolicyLuaFFI", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'"}, + {"setPoolServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy for this pool to one named 'name' and returned by the Lua FFI code passed in 'code'"}, + {"setProxyProtocolACL", true, "{netmask, netmask}", "Set the netmasks who are allowed to send Proxy Protocol headers in front of queries/connections"}, + {"setProxyProtocolApplyACLToProxiedClients", true, "apply", "Whether the general ACL should be applied to the source IP address gathered from a Proxy Protocol header, in addition to being first applied to the source address seen by dnsdist"}, + {"setProxyProtocolMaximumPayloadSize", true, "max", "Set the maximum size of a Proxy Protocol payload, in bytes"}, + {"setQueryCount", true, "bool", "set whether queries should be counted"}, + {"setQueryCountFilter", true, "func", "filter queries that would be counted, where `func` is a function with parameter `dq` which decides whether a query should and how it should be counted"}, + {"SetReducedTTLResponseAction", true, "percentage", "Reduce the TTL of records in a response to a given percentage"}, + {"setRingBuffersLockRetries", true, "n", "set the number of attempts to get a non-blocking lock to a ringbuffer shard before blocking"}, + {"setRingBuffersOptions", true, "{ lockRetries=int, recordQueries=true, recordResponses=true }", "set ringbuffer options"}, + {"setRingBuffersSize", true, "n [, numberOfShards]", "set the capacity of the ringbuffers used for live traffic inspection to `n`, and optionally the number of shards to use to `numberOfShards`"}, + {"setRoundRobinFailOnNoServer", true, "value", "By default the roundrobin load-balancing policy will still try to select a backend even if all backends are currently down. Setting this to true will make the policy fail and return that no server is available instead"}, + {"setRules", true, "list of rules", "replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see `newRuleAction()`)"}, + {"setSecurityPollInterval", true, "n", "set the security polling interval to `n` seconds"}, + {"setSecurityPollSuffix", true, "suffix", "set the security polling suffix to the specified value"}, + {"setServerPolicy", true, "policy", "set server selection policy to that policy"}, + {"setServerPolicyLua", true, "name, function", "set server selection policy to one named 'name' and provided by 'function'"}, + {"setServerPolicyLuaFFI", true, "name, function", "set server selection policy to one named 'name' and provided by the Lua FFI 'function'"}, + {"setServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy to one named 'name' and returned by the Lua FFI code passed in 'code'"}, + {"setServFailWhenNoServer", true, "bool", "if set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query"}, + {"setStaleCacheEntriesTTL", true, "n", "allows using cache entries expired for at most n seconds when there is no backend available to answer for a query"}, + {"setStructuredLogging", true, "value [, options]", "set whether log messages should be in structured-logging-like format"}, + {"setSyslogFacility", true, "facility", "set the syslog logging facility to 'facility'. Defaults to LOG_DAEMON"}, + {"setTCPDownstreamCleanupInterval", true, "interval", "minimum interval in seconds between two cleanups of the idle TCP downstream connections"}, + {"setTCPFastOpenKey", true, "string", "TCP Fast Open Key"}, + {"setTCPDownstreamMaxIdleTime", true, "time", "Maximum time in seconds that a downstream TCP connection to a backend might stay idle"}, + {"setTCPInternalPipeBufferSize", true, "size", "Set the size in bytes of the internal buffer of the pipes used internally to distribute connections to TCP (and DoT) workers threads"}, + {"setTCPRecvTimeout", true, "n", "set the read timeout on TCP connections from the client, in seconds"}, + {"setTCPSendTimeout", true, "n", "set the write timeout on TCP connections from the client, in seconds"}, + {"setUDPMultipleMessagesVectorSize", true, "n", "set the size of the vector passed to recvmmsg() to receive UDP messages. Default to 1 which means that the feature is disabled and recvmsg() is used instead"}, + {"setUDPSocketBufferSizes", true, "recv, send", "Set the size of the receive (SO_RCVBUF) and send (SO_SNDBUF) buffers for incoming UDP sockets"}, + {"setUDPTimeout", true, "n", "set the maximum time dnsdist will wait for a response from a backend over UDP, in seconds"}, + {"setVerbose", true, "bool", "set whether log messages at the verbose level will be logged"}, + {"setVerboseHealthChecks", true, "bool", "set whether health check errors will be logged"}, + {"setVerboseLogDestination", true, "destination file", "Set a destination file to write the 'verbose' log messages to, instead of sending them to syslog and/or the standard output"}, + {"setWebserverConfig", true, "[{password=string, apiKey=string, customHeaders, statsRequireAuthentication}]", "Updates webserver configuration"}, + {"setWeightedBalancingFactor", true, "factor", "Set the balancing factor for bounded-load weighted policies (whashed, wrandom)"}, + {"setWHashedPertubation", true, "value", "Set the hash perturbation value to be used in the whashed policy instead of a random one, allowing to have consistent whashed results on different instance"}, + {"show", true, "string", "outputs `string`"}, + {"showACL", true, "", "show our ACL set"}, + {"showBinds", true, "", "show listening addresses (frontends)"}, + {"showCacheHitResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined cache hit response rules, optionally with their UUIDs and optionally truncated to a given width"}, + {"showConsoleACL", true, "", "show our current console ACL set"}, + {"showDNSCryptBinds", true, "", "display the currently configured DNSCrypt binds"}, + {"showDOHFrontends", true, "", "list all the available DOH frontends"}, + {"showDOH3Frontends", true, "", "list all the available DOH3 frontends"}, + {"showDOHResponseCodes", true, "", "show the HTTP response code statistics for the DoH frontends"}, + {"showDOQFrontends", true, "", "list all the available DOQ frontends"}, + {"showDynBlocks", true, "", "show dynamic blocks in force"}, + {"showPools", true, "", "show the available pools"}, + {"showPoolServerPolicy", true, "pool", "show server selection policy for this pool"}, + {"showResponseLatency", true, "", "show a plot of the response time latency distribution"}, + {"showResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined response rules, optionally with their UUIDs and optionally truncated to a given width"}, + {"showRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined rules, optionally with their UUIDs and optionally truncated to a given width"}, + {"showSecurityStatus", true, "", "Show the security status"}, + {"showSelfAnsweredResponseRules", true, "[{showUUIDs=false, truncateRuleWidth=-1}]", "show all defined self-answered response rules, optionally with their UUIDs and optionally truncated to a given width"}, + {"showServerPolicy", true, "", "show name of currently operational server selection policy"}, + {"showServers", true, "[{showUUIDs=false}]", "output all servers, optionally with their UUIDs"}, + {"showTCPStats", true, "", "show some statistics regarding TCP"}, + {"showTLSContexts", true, "", "list all the available TLS contexts"}, + {"showTLSErrorCounters", true, "", "show metrics about TLS handshake failures"}, + {"showVersion", true, "", "show the current version"}, + {"showWebserverConfig", true, "", "Show the current webserver configuration"}, + {"shutdown", true, "", "shut down `dnsdist`"}, + {"snmpAgent", true, "enableTraps [, daemonSocket]", "enable `SNMP` support. `enableTraps` is a boolean indicating whether traps should be sent and `daemonSocket` an optional string specifying how to connect to the daemon agent"}, + {"SetAdditionalProxyProtocolValueAction", true, "type, value", "Add a Proxy Protocol TLV value of this type"}, + {"SetDisableECSAction", true, "", "Disable the sending of ECS to the backend. Subsequent rules are processed after this action."}, + {"SetDisableValidationAction", true, "", "set the CD bit in the question, let it go through"}, + {"SetECSAction", true, "v4[, v6]", "Set the ECS prefix and prefix length sent to backends to an arbitrary value"}, + {"SetECSOverrideAction", true, "override", "Whether an existing EDNS Client Subnet value should be overridden (true) or not (false). Subsequent rules are processed after this action"}, + {"SetECSPrefixLengthAction", true, "v4, v6", "Set the ECS prefix length. Subsequent rules are processed after this action"}, + {"SetMacAddrAction", true, "option", "Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this action"}, + {"SetEDNSOptionAction", true, "option, data", "Add arbitrary EDNS option and data to the query. Subsequent rules are processed after this action"}, + {"SetExtendedDNSErrorAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action"}, + {"SetExtendedDNSErrorResponseAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to this response. Subsequent rules are processed after this action"}, + {"SetNoRecurseAction", true, "", "strip RD bit from the question, let it go through"}, + {"setOutgoingDoHWorkerThreads", true, "n", "Number of outgoing DoH worker threads"}, + {"SetProxyProtocolValuesAction", true, "values", "Set the Proxy-Protocol values for this queries to 'values'"}, + {"SetSkipCacheAction", true, "", "Don’t lookup the cache for this query, don’t store the answer"}, + {"SetSkipCacheResponseAction", true, "", "Don’t store this response into the cache"}, + {"SetTagAction", true, "name, value", "set the tag named 'name' to the given value"}, + {"SetTagResponseAction", true, "name, value", "set the tag named 'name' to the given value"}, + {"SetTempFailureCacheTTLAction", true, "ttl", "set packetcache TTL for temporary failure replies"}, + {"SNIRule", true, "name", "Create a rule which matches on the incoming TLS SNI value, if any (DoT or DoH)"}, + {"SNMPTrapAction", true, "[reason]", "send an SNMP trap, adding the optional `reason` string as the query description"}, + {"SNMPTrapResponseAction", true, "[reason]", "send an SNMP trap, adding the optional `reason` string as the response description"}, + {"SpoofAction", true, "ip|list of ips [, options]", "forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA). If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in"}, + {"SpoofCNAMEAction", true, "cname [, options]", "Forge a response with the specified CNAME value"}, + {"SpoofRawAction", true, "raw|list of raws [, options]", "Forge a response with the specified record data as raw bytes. If you specify multiple raws (it is assumed they match the query type), all will get spoofed in"}, + {"SpoofSVCAction", true, "list of svcParams [, options]", "Forge a response with the specified SVC record data"}, + {"SuffixMatchNodeRule", true, "smn[, quiet]", "Matches based on a group of domain suffixes for rapid testing of membership. Pass true as second parameter to prevent listing of all domains matched"}, + {"TagRule", true, "name [, value]", "matches if the tag named 'name' is present, with the given 'value' matching if any"}, + {"TCAction", true, "", "create answer to query with TC and RD bits set, to move to TCP"}, + {"TCPRule", true, "[tcp]", "Matches question received over TCP if tcp is true, over UDP otherwise"}, + {"TCResponseAction", true, "", "truncate a response"}, + {"TeeAction", true, "remote [, addECS [, local]]", "send copy of query to remote, optionally adding ECS info, optionally set local address"}, + {"testCrypto", true, "", "test of the crypto all works"}, + {"TimedIPSetRule", true, "", "Create a rule which matches a set of IP addresses which expire"}, + {"topBandwidth", true, "top", "show top-`top` clients that consume the most bandwidth over length of ringbuffer"}, + {"topCacheHitResponseRules", true, "[top][, vars]", "show `top` cache-hit response rules"}, + {"topCacheInsertedResponseRules", true, "[top][, vars]", "show `top` cache-inserted response rules"}, + {"topClients", true, "n", "show top-`n` clients sending the most queries over length of ringbuffer"}, + {"topQueries", true, "n[, labels]", "show top 'n' queries, as grouped when optionally cut down to 'labels' labels"}, + {"topResponses", true, "n, kind[, labels]", "show top 'n' responses with RCODE=kind (0=NO Error, 2=ServFail, 3=NXDomain), as grouped when optionally cut down to 'labels' labels"}, + {"topResponseRules", true, "[top][, vars]", "show `top` response rules"}, + {"topRules", true, "[top][, vars]", "show `top` rules"}, + {"topSelfAnsweredResponseRules", true, "[top][, vars]", "show `top` self-answered response rules"}, + {"topSlow", true, "[top][, limit][, labels]", "show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels"}, + {"TrailingDataRule", true, "", "Matches if the query has trailing data"}, + {"truncateTC", true, "bool", "if set (defaults to no starting with dnsdist 1.2.0) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22. Note: turning this on breaks compatibility with RFC 6891."}, + {"unregisterDynBPFFilter", true, "DynBPFFilter", "unregister this dynamic BPF filter"}, + {"webserver", true, "address:port", "launch a webserver with stats on that address"}, + {"whashed", false, "", "Weighted hashed ('sticky') distribution over available servers, based on the server 'weight' parameter"}, + {"chashed", false, "", "Consistent hashed ('sticky') distribution over available servers, also based on the server 'weight' parameter"}, + {"wrandom", false, "", "Weighted random over available servers, based on the server 'weight' parameter"}, }; #if defined(HAVE_LIBEDIT) -extern "C" { -static char* my_generator(const char* text, int state) +extern "C" { - string textStr(text); - /* to keep it readable, we try to keep only 4 keywords per line - and to start a new line when the first letter changes */ - static int s_counter = 0; - int counter = 0; - if (state == 0) { - s_counter = 0; - } + static char* my_generator(const char* text, int state) + { + string textStr(text); + /* to keep it readable, we try to keep only 4 keywords per line + and to start a new line when the first letter changes */ + static int s_counter = 0; + int counter = 0; + if (state == 0) { + s_counter = 0; + } - for (const auto& keyword : g_consoleKeywords) { - if (boost::starts_with(keyword.name, textStr) && counter++ == s_counter) { - std::string value(keyword.name); - s_counter++; - if (keyword.function) { - value += "("; - if (keyword.parameters.empty()) { - value += ")"; + for (const auto& keyword : g_consoleKeywords) { + if (boost::starts_with(keyword.name, textStr) && counter++ == s_counter) { + std::string value(keyword.name); + s_counter++; + if (keyword.function) { + value += "("; + if (keyword.parameters.empty()) { + value += ")"; + } } + return strdup(value.c_str()); } - return strdup(value.c_str()); } + return nullptr; } - return nullptr; -} -char** my_completion( const char * text , int start, int end) -{ - char **matches = nullptr; - if (start == 0) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): readline - matches = rl_completion_matches (const_cast(text), &my_generator); - } + char** my_completion(const char* text, int start, int end) + { + char** matches = nullptr; + if (start == 0) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): readline + matches = rl_completion_matches(const_cast(text), &my_generator); + } - // skip default filename completion. - rl_attempted_completion_over = 1; + // skip default filename completion. + rl_attempted_completion_over = 1; - return matches; -} + return matches; + } } #endif /* HAVE_LIBEDIT */ #endif /* DISABLE_COMPLETION */ @@ -938,37 +940,36 @@ static void controlClientThread(ConsoleConnection&& conn) string, shared_ptr, ClientState*, - std::unordered_map - > - > - >(withReturn ? ("return "+line) : line); + std::unordered_map>>>(withReturn ? ("return " + line) : line); if (ret) { if (const auto* dsValue = boost::get>(&*ret)) { if (*dsValue) { - response = (*dsValue)->getName()+"\n"; - } else { + response = (*dsValue)->getName() + "\n"; + } + else { response = ""; } } else if (const auto* csValue = boost::get(&*ret)) { if (*csValue != nullptr) { - response = (*csValue)->local.toStringWithPort()+"\n"; - } else { + response = (*csValue)->local.toStringWithPort() + "\n"; + } + else { response = ""; } } else if (const auto* strValue = boost::get(&*ret)) { - response = *strValue+"\n"; + response = *strValue + "\n"; } - else if (const auto* mapValue = boost::get >(&*ret)) { + else if (const auto* mapValue = boost::get>(&*ret)) { using namespace json11; Json::object obj; for (const auto& value : *mapValue) { obj[value.first] = value.second; } Json out = obj; - response = out.dump()+"\n"; + response = out.dump() + "\n"; } } else { @@ -987,12 +988,12 @@ static void controlClientThread(ConsoleConnection&& conn) throw; } } - catch(const LuaContext::WrongTypeException& e) { - response = "Command returned an object we can't print: " +std::string(e.what()) + "\n"; + catch (const LuaContext::WrongTypeException& e) { + response = "Command returned an object we can't print: " + std::string(e.what()) + "\n"; // tried to return something we don't understand } catch (const LuaContext::ExecutionErrorException& e) { - if (strcmp(e.what(),"invalid key to 'next'") == 0) { + if (strcmp(e.what(), "invalid key to 'next'") == 0) { response = "Error: Parsing function parameters, did you forget parameter name?"; } else { @@ -1001,9 +1002,10 @@ static void controlClientThread(ConsoleConnection&& conn) try { std::rethrow_if_nested(e); - } catch (const std::exception& ne) { + } + catch (const std::exception& ne) { // ne is the exception that was thrown from inside the lambda - response+= ": " + string(ne.what()); + response += ": " + string(ne.what()); } catch (const PDNSException& ne) { // ne is the exception that was thrown from inside the lambda @@ -1029,8 +1031,7 @@ static void controlClientThread(ConsoleConnection&& conn) // NOLINTNEXTLINE(performance-unnecessary-value-param): this is thread void controlThread(std::shared_ptr acceptFD, ComboAddress local) { - try - { + try { setThreadName("dnsdist/control"); ComboAddress client; int sock{-1}; diff --git a/pdns/dnsdistdist/dnsdist-console.hh b/pdns/dnsdistdist/dnsdist-console.hh index 6e227d4716..dd833c49e4 100644 --- a/pdns/dnsdistdist/dnsdist-console.hh +++ b/pdns/dnsdistdist/dnsdist-console.hh @@ -25,7 +25,8 @@ #include "sstuff.hh" #ifndef DISABLE_COMPLETION -struct ConsoleKeyword { +struct ConsoleKeyword +{ std::string name; bool function; std::string parameters; @@ -42,8 +43,9 @@ struct ConsoleKeyword { } }; extern const std::vector g_consoleKeywords; -extern "C" { -char** my_completion( const char * text , int start, int end); +extern "C" +{ + char** my_completion(const char* text, int start, int end); } #endif /* DISABLE_COMPLETION */ diff --git a/pdns/dnsdistdist/dnsdist-dynbpf.cc b/pdns/dnsdistdist/dnsdist-dynbpf.cc index 9ede03fabf..54902b367e 100644 --- a/pdns/dnsdistdist/dnsdist-dynbpf.cc +++ b/pdns/dnsdistdist/dnsdist-dynbpf.cc @@ -49,10 +49,10 @@ void DynBPFFilter::purgeExpired(const struct timespec& now) { auto data = d_data.lock(); - typedef boost::multi_index::nth_index::type ordered_until; + typedef boost::multi_index::nth_index::type ordered_until; ordered_until& ou = boost::multi_index::get<1>(data->d_entries); - for (ordered_until::iterator it = ou.begin(); it != ou.end(); ) { + for (ordered_until::iterator it = ou.begin(); it != ou.end();) { if (it->d_until < now) { ComboAddress addr = it->d_addr; it = ou.erase(it); @@ -64,9 +64,9 @@ void DynBPFFilter::purgeExpired(const struct timespec& now) } } -std::vector > DynBPFFilter::getAddrStats() +std::vector> DynBPFFilter::getAddrStats() { - std::vector > result; + std::vector> result; auto data = d_data.lock(); if (!data->d_bpf) { diff --git a/pdns/dnsdistdist/dnsdist-dynbpf.hh b/pdns/dnsdistdist/dnsdist-dynbpf.hh index 907a7300b9..cfb5d6b3c2 100644 --- a/pdns/dnsdistdist/dnsdist-dynbpf.hh +++ b/pdns/dnsdistdist/dnsdist-dynbpf.hh @@ -50,27 +50,28 @@ public: /* returns true if the addr wasn't already blocked, false otherwise */ bool block(const ComboAddress& addr, const struct timespec& until); void purgeExpired(const struct timespec& now); - std::vector > getAddrStats(); + std::vector> getAddrStats(); + private: struct BlockEntry { - BlockEntry(const ComboAddress& addr, const struct timespec until): d_addr(addr), d_until(until) + BlockEntry(const ComboAddress& addr, const struct timespec until) : + d_addr(addr), d_until(until) { } ComboAddress d_addr; struct timespec d_until; }; typedef boost::multi_index_container, ComboAddress::addressOnlyLessThan >, - boost::multi_index::ordered_non_unique< boost::multi_index::member > - > - > container_t; - struct Data { + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique, ComboAddress::addressOnlyLessThan>, + boost::multi_index::ordered_non_unique>>> + container_t; + struct Data + { container_t d_entries; std::shared_ptr d_bpf{nullptr}; NetmaskGroup d_excludedSubnets; }; LockGuarded d_data; }; - diff --git a/pdns/dnsdistdist/dnsdist-ecs.cc b/pdns/dnsdistdist/dnsdist-ecs.cc index 2cad1945bc..5fa61c5b19 100644 --- a/pdns/dnsdistdist/dnsdist-ecs.cc +++ b/pdns/dnsdistdist/dnsdist-ecs.cc @@ -73,24 +73,24 @@ int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& rrclass = pr.get16BitInt(); GenericDNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode); - pw.getHeader()->id=dh->id; - pw.getHeader()->qr=dh->qr; - pw.getHeader()->aa=dh->aa; - pw.getHeader()->tc=dh->tc; - pw.getHeader()->rd=dh->rd; - pw.getHeader()->ra=dh->ra; - pw.getHeader()->ad=dh->ad; - pw.getHeader()->cd=dh->cd; - pw.getHeader()->rcode=dh->rcode; + pw.getHeader()->id = dh->id; + pw.getHeader()->qr = dh->qr; + pw.getHeader()->aa = dh->aa; + pw.getHeader()->tc = dh->tc; + pw.getHeader()->rd = dh->rd; + pw.getHeader()->ra = dh->ra; + pw.getHeader()->ad = dh->ad; + pw.getHeader()->cd = dh->cd; + pw.getHeader()->rcode = dh->rcode; /* consume remaining qd if any */ if (qdcount > 1) { - for(idx = 1; idx < qdcount; idx++) { + for (idx = 1; idx < qdcount; idx++) { rrname = pr.getName(); rrtype = pr.get16BitInt(); rrclass = pr.get16BitInt(); - (void) rrtype; - (void) rrclass; + (void)rrtype; + (void)rrclass; } } @@ -121,7 +121,8 @@ int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, true); pr.xfrBlob(blob); pw.xfrBlob(blob); - } else { + } + else { pr.skip(ah.d_clen); } @@ -133,7 +134,7 @@ int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& static bool addOrReplaceEDNSOption(std::vector>& options, uint16_t optionCode, bool& optionAdded, bool overrideExisting, const string& newOptionContent) { - for (auto it = options.begin(); it != options.end(); ) { + for (auto it = options.begin(); it != options.end();) { if (it->first == optionCode) { optionAdded = false; @@ -186,24 +187,24 @@ bool slowRewriteEDNSOptionInQueryWithRecords(const PacketBuffer& initialPacket, rrclass = pr.get16BitInt(); GenericDNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode); - pw.getHeader()->id=dh->id; - pw.getHeader()->qr=dh->qr; - pw.getHeader()->aa=dh->aa; - pw.getHeader()->tc=dh->tc; - pw.getHeader()->rd=dh->rd; - pw.getHeader()->ra=dh->ra; - pw.getHeader()->ad=dh->ad; - pw.getHeader()->cd=dh->cd; - pw.getHeader()->rcode=dh->rcode; + pw.getHeader()->id = dh->id; + pw.getHeader()->qr = dh->qr; + pw.getHeader()->aa = dh->aa; + pw.getHeader()->tc = dh->tc; + pw.getHeader()->rd = dh->rd; + pw.getHeader()->ra = dh->ra; + pw.getHeader()->ad = dh->ad; + pw.getHeader()->cd = dh->cd; + pw.getHeader()->rcode = dh->rcode; /* consume remaining qd if any */ if (qdcount > 1) { - for(idx = 1; idx < qdcount; idx++) { + for (idx = 1; idx < qdcount; idx++) { rrname = pr.getName(); rrtype = pr.get16BitInt(); rrclass = pr.get16BitInt(); - (void) rrtype; - (void) rrclass; + (void)rrtype; + (void)rrclass; } } @@ -235,7 +236,8 @@ bool slowRewriteEDNSOptionInQueryWithRecords(const PacketBuffer& initialPacket, pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, true); pr.xfrBlob(blob); pw.xfrBlob(blob); - } else { + } + else { ednsAdded = false; pr.xfrBlob(blob); @@ -286,13 +288,13 @@ static bool slowParseEDNSOptions(const PacketBuffer& packet, EDNSOptionViewMap& uint64_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount); DNSPacketMangler dpm(const_cast(reinterpret_cast(&packet.at(0))), packet.size()); uint64_t n; - for(n=0; n < ntohs(dh->qdcount) ; ++n) { + for (n = 0; n < ntohs(dh->qdcount); ++n) { dpm.skipDomainName(); /* type and class */ dpm.skipBytes(4); } - for(n=0; n < numrecords; ++n) { + for (n = 0; n < numrecords; ++n) { dpm.skipDomainName(); uint8_t section = n < ntohs(dh->ancount) ? 1 : (n < (ntohs(dh->ancount) + ntohs(dh->nscount)) ? 2 : 3); @@ -300,7 +302,7 @@ static bool slowParseEDNSOptions(const PacketBuffer& packet, EDNSOptionViewMap& dpm.get16BitInt(); dpm.skipBytes(4); /* TTL */ - if(section == 3 && dnstype == QType::OPT) { + if (section == 3 && dnstype == QType::OPT) { uint32_t offset = dpm.getOffset(); if (offset >= packet.size()) { return false; @@ -314,15 +316,14 @@ static bool slowParseEDNSOptions(const PacketBuffer& packet, EDNSOptionViewMap& } } } - catch(...) - { + catch (...) { return false; } return true; } -int locateEDNSOptRR(const PacketBuffer& packet, uint16_t * optStart, size_t * optLen, bool * last) +int locateEDNSOptRR(const PacketBuffer& packet, uint16_t* optStart, size_t* optLen, bool* last) { assert(optStart != NULL); assert(optLen != NULL); @@ -346,12 +347,12 @@ int locateEDNSOptRR(const PacketBuffer& packet, uint16_t * optStart, size_t * op struct dnsrecordheader ah; /* consume qd */ - for(idx = 0; idx < qdcount; idx++) { + for (idx = 0; idx < qdcount; idx++) { rrname = pr.getName(); rrtype = pr.get16BitInt(); rrclass = pr.get16BitInt(); - (void) rrtype; - (void) rrclass; + (void)rrtype; + (void)rrclass; } /* consume AN and NS */ @@ -375,7 +376,7 @@ int locateEDNSOptRR(const PacketBuffer& packet, uint16_t * optStart, size_t * op throw std::range_error("Opt record overflow"); } - if (idx == ((size_t) arcount - 1)) { + if (idx == ((size_t)arcount - 1)) { *last = true; } else { @@ -420,7 +421,7 @@ int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_ } pos += 1; - uint16_t qtype = packet.at(pos)*256 + packet.at(pos+1); + uint16_t qtype = packet.at(pos) * 256 + packet.at(pos + 1); pos += DNS_TYPE_SIZE; pos += DNS_CLASS_SIZE; @@ -647,7 +648,8 @@ bool handleEDNSClientSubnet(PacketBuffer& packet, const size_t maximumSize, cons } return replaceEDNSClientSubnetOption(packet, maximumSize, optRDPosition + ecsOptionStartPosition, ecsOptionSize, optRDPosition, newECSOption); - } else { + } + else { /* we have an EDNS OPT RR but no existing ECS option */ return addECSToExistingOPT(packet, maximumSize, newECSOption, optRDPosition, ecsAdded); } @@ -669,10 +671,10 @@ static int removeEDNSOptionFromOptions(unsigned char* optionsStart, const uint16 size_t pos = 0; while ((pos + 4) <= optionsLen) { unsigned char* optionBegin = p; - const uint16_t optionCode = 0x100*p[0] + p[1]; + const uint16_t optionCode = 0x100 * p[0] + p[1]; p += sizeof(optionCode); pos += sizeof(optionCode); - const uint16_t optionLen = 0x100*p[0] + p[1]; + const uint16_t optionLen = 0x100 * p[0] + p[1]; p += sizeof(optionLen); pos += sizeof(optionLen); if ((pos + optionLen) > optionsLen) { @@ -698,10 +700,10 @@ int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optio if (*optLen < optRecordMinimumSize) { return EINVAL; } - const unsigned char* end = (const unsigned char*) optStart + *optLen; - unsigned char* p = (unsigned char*) optStart + 9; + const unsigned char* end = (const unsigned char*)optStart + *optLen; + unsigned char* p = (unsigned char*)optStart + 9; unsigned char* rdLenPtr = p; - uint16_t rdLen = (0x100*p[0] + p[1]); + uint16_t rdLen = (0x100 * p[0] + p[1]); p += sizeof(rdLen); if (p + rdLen != end) { return EINVAL; @@ -723,7 +725,7 @@ bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const return false; } size_t p = optStart + 9; - uint16_t rdLen = (0x100*static_cast(packet.at(p)) + static_cast(packet.at(p+1))); + uint16_t rdLen = (0x100 * static_cast(packet.at(p)) + static_cast(packet.at(p + 1))); p += sizeof(rdLen); if (rdLen > (optLen - optRecordMinimumSize)) { return false; @@ -731,9 +733,9 @@ bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const size_t rdEnd = p + rdLen; while ((p + 4) <= rdEnd) { - const uint16_t optionCode = 0x100*static_cast(packet.at(p)) + static_cast(packet.at(p+1)); + const uint16_t optionCode = 0x100 * static_cast(packet.at(p)) + static_cast(packet.at(p + 1)); p += sizeof(optionCode); - const uint16_t optionLen = 0x100*static_cast(packet.at(p)) + static_cast(packet.at(p+1)); + const uint16_t optionLen = 0x100 * static_cast(packet.at(p)) + static_cast(packet.at(p + 1)); p += sizeof(optionLen); if ((p + optionLen) > rdEnd) { @@ -785,24 +787,24 @@ int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const ui rrclass = pr.get16BitInt(); GenericDNSPacketWriter pw(newContent, rrname, rrtype, rrclass, dh->opcode); - pw.getHeader()->id=dh->id; - pw.getHeader()->qr=dh->qr; - pw.getHeader()->aa=dh->aa; - pw.getHeader()->tc=dh->tc; - pw.getHeader()->rd=dh->rd; - pw.getHeader()->ra=dh->ra; - pw.getHeader()->ad=dh->ad; - pw.getHeader()->cd=dh->cd; - pw.getHeader()->rcode=dh->rcode; + pw.getHeader()->id = dh->id; + pw.getHeader()->qr = dh->qr; + pw.getHeader()->aa = dh->aa; + pw.getHeader()->tc = dh->tc; + pw.getHeader()->rd = dh->rd; + pw.getHeader()->ra = dh->ra; + pw.getHeader()->ad = dh->ad; + pw.getHeader()->cd = dh->cd; + pw.getHeader()->rcode = dh->rcode; /* consume remaining qd if any */ if (qdcount > 1) { - for(idx = 1; idx < qdcount; idx++) { + for (idx = 1; idx < qdcount; idx++) { rrname = pr.getName(); rrtype = pr.get16BitInt(); rrclass = pr.get16BitInt(); - (void) rrtype; - (void) rrclass; + (void)rrtype; + (void)rrclass; } } @@ -834,7 +836,8 @@ int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const ui pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, true); pr.xfrBlob(blob); pw.xfrBlob(blob); - } else { + } + else { pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, DNSResourceRecord::ADDITIONAL, false); pr.xfrBlob(blob); uint16_t rdLen = blob.length(); @@ -843,7 +846,8 @@ int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const ui if (rdLen > 0) { blob.resize((size_t)rdLen); pw.xfrBlob(blob); - } else { + } + else { pw.commit(); } } @@ -952,7 +956,8 @@ bool setNegativeAndAdditionalSOA(DNSQuestion& dq, bool nxd, const DNSName& zone, dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [soaInAuthoritySection](dnsheader& header) { if (soaInAuthoritySection) { header.nscount = htons(1); - } else { + } + else { header.arcount = htons(1); } return true; @@ -1012,8 +1017,7 @@ bool addEDNSToQueryTurnedResponse(DNSQuestion& dq) // goal in life - if you send us a reasonably normal packet, we'll get Z for you, otherwise 0 int getEDNSZ(const DNSQuestion& dq) { - try - { + try { const auto& dh = dq.getHeader(); if (ntohs(dh->qdcount) != 1 || dh->ancount != 0 || ntohs(dh->arcount) != 1 || dh->nscount != 0) { return 0; @@ -1038,7 +1042,7 @@ int getEDNSZ(const DNSQuestion& dq) pos++; - uint16_t qtype = packet.at(pos)*256 + packet.at(pos+1); + uint16_t qtype = packet.at(pos) * 256 + packet.at(pos + 1); pos += DNS_TYPE_SIZE; pos += DNS_CLASS_SIZE; @@ -1047,10 +1051,9 @@ int getEDNSZ(const DNSQuestion& dq) } const uint8_t* z = &packet.at(pos + EDNS_EXTENDED_RCODE_SIZE + EDNS_VERSION_SIZE); - return 0x100 * (*z) + *(z+1); + return 0x100 * (*z) + *(z + 1); } - catch(...) - { + catch (...) { return 0; } } @@ -1134,8 +1137,9 @@ bool setEDNSOption(DNSQuestion& dq, uint16_t ednsCode, const std::string& ednsDa return true; } -namespace dnsdist { -bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uint8_t rcode, bool clearAnswers) +namespace dnsdist +{ +bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uint8_t rcode, bool clearAnswers) { const auto qnameLength = state.qname.wirelength(); if (buffer.size() < sizeof(dnsheader) + qnameLength + sizeof(uint16_t) + sizeof(uint16_t)) { @@ -1148,7 +1152,7 @@ bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uin hadEDNS = getEDNS0Record(buffer, edns0); } - dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [rcode,clearAnswers](dnsheader& header) { + dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [rcode, clearAnswers](dnsheader& header) { header.rcode = rcode; header.ad = false; header.aa = false; diff --git a/pdns/dnsdistdist/dnsdist-ecs.hh b/pdns/dnsdistdist/dnsdist-ecs.hh index f5d215f1a0..3af754d8af 100644 --- a/pdns/dnsdistdist/dnsdist-ecs.hh +++ b/pdns/dnsdistdist/dnsdist-ecs.hh @@ -36,12 +36,12 @@ 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); +int locateEDNSOptRR(const PacketBuffer& packet, uint16_t* optStart, size_t* optLen, bool* last); bool generateOptRR(const std::string& optRData, PacketBuffer& res, size_t maximumSize, uint16_t udpPayloadSize, uint8_t ednsrcode, bool dnssecOK); void generateECSOption(const ComboAddress& source, string& res, uint16_t ECSPrefixLength); int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove); int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const uint16_t optionCodeToSkip, PacketBuffer& newContent); -int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_t* optRDPosition, size_t * remaining); +int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_t* optRDPosition, size_t* remaining); bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart = nullptr, uint16_t* optContentLen = nullptr); bool addEDNS(PacketBuffer& packet, size_t maximumSize, bool dnssecOK, uint16_t payloadSize, uint8_t ednsrcode); bool addEDNSToQueryTurnedResponse(DNSQuestion& dq); @@ -59,6 +59,7 @@ bool getEDNS0Record(const PacketBuffer& packet, EDNS0Record& edns0); bool setEDNSOption(DNSQuestion& dq, uint16_t ednsCode, const std::string& data); struct InternalQueryState; -namespace dnsdist { -bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uint8_t rcode, bool clearAnswers); +namespace dnsdist +{ +bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer, uint8_t rcode, bool clearAnswers); } diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.hh b/pdns/dnsdistdist/dnsdist-lbpolicies.hh index 72443402d1..78fcb22016 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.hh +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.hh @@ -32,16 +32,19 @@ struct PerThreadPoliciesState; class ServerPolicy { public: - template using NumberedVector = std::vector >; + template + using NumberedVector = std::vector>; using NumberedServerVector = NumberedVector>; typedef std::function(const NumberedServerVector& servers, const DNSQuestion*)> policyfunc_t; typedef std::function ffipolicyfunc_t; - ServerPolicy(const std::string& name_, policyfunc_t policy_, bool isLua_): d_name(name_), d_policy(std::move(policy_)), d_isLua(isLua_) + ServerPolicy(const std::string& name_, policyfunc_t policy_, bool isLua_) : + d_name(name_), d_policy(std::move(policy_)), d_isLua(isLua_) { } - ServerPolicy(const std::string& name_, ffipolicyfunc_t policy_): d_name(name_), d_ffipolicy(std::move(policy_)), d_isLua(true), d_isFFI(true) + ServerPolicy(const std::string& name_, ffipolicyfunc_t policy_) : + d_name(name_), d_ffipolicy(std::move(policy_)), d_isLua(true), d_isFFI(true) { } @@ -59,7 +62,8 @@ public: return d_name; } - std::string toString() const { + std::string toString() const + { return string("ServerPolicy") + (d_isLua ? " (Lua)" : "") + " \"" + d_name + "\""; } @@ -74,7 +78,6 @@ private: const ffipolicyfunc_t& getPerThreadPolicy() const; static thread_local PerThreadState t_perThreadState; - public: std::string d_name; std::string d_perThreadPolicyCode; @@ -96,7 +99,7 @@ void setPoolPolicy(pools_t& pools, const string& poolName, std::shared_ptr server); void removeServerFromPool(pools_t& pools, const string& poolName, std::shared_ptr server); -const std::shared_ptr getDownstreamCandidates(const map>& pools, const std::string& poolName); +const std::shared_ptr getDownstreamCandidates(const map>& pools, const std::string& poolName); std::shared_ptr firstAvailable(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq); diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc index 4512fc5ef4..deb8c3f7ac 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc @@ -33,80 +33,88 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) #ifndef DISABLE_NON_FFI_DQ_BINDINGS /* DNSQuestion */ /* PowerDNS DNSQuestion compat */ - luaCtx.registerMember("localaddr", [](const DNSQuestion& dq) -> const ComboAddress { return dq.ids.origDest; }, [](DNSQuestion& dq, const ComboAddress newLocal) { (void) newLocal; }); - luaCtx.registerMember("qname", [](const DNSQuestion& dq) -> const DNSName { return dq.ids.qname; }, [](DNSQuestion& dq, const DNSName& newName) { (void) newName; }); - luaCtx.registerMember("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; }); - luaCtx.registerMember("qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void) newClass; }); - luaCtx.registerMember("rcode", [](const DNSQuestion& dq) -> int { return static_cast(dq.getHeader()->rcode); }, [](DNSQuestion& dq, int newRCode) { - dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) { - header.rcode = static_cast(newRCode); - return true; - }); - }); - luaCtx.registerMember("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void) newRemote; }); + luaCtx.registerMember( + "localaddr", [](const DNSQuestion& dq) -> const ComboAddress { return dq.ids.origDest; }, [](DNSQuestion& dq, const ComboAddress newLocal) { (void)newLocal; }); + luaCtx.registerMember( + "qname", [](const DNSQuestion& dq) -> const DNSName { return dq.ids.qname; }, [](DNSQuestion& dq, const DNSName& newName) { (void)newName; }); + luaCtx.registerMember( + "qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void)newType; }); + luaCtx.registerMember( + "qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void)newClass; }); + luaCtx.registerMember( + "rcode", [](const DNSQuestion& dq) -> int { return static_cast(dq.getHeader()->rcode); }, [](DNSQuestion& dq, int newRCode) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) { + header.rcode = static_cast(newRCode); + return true; + }); }); + luaCtx.registerMember( + "remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void)newRemote; }); /* DNSDist DNSQuestion */ - luaCtx.registerMember("dh", [](const DNSQuestion& dq) -> dnsheader* { return dq.getMutableHeader(); }, [](DNSQuestion& dq, const dnsheader* dh) { - dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [&dh](dnsheader& header) { - header = *dh; - return true; - }); - }); - luaCtx.registerMember("len", [](const DNSQuestion& dq) -> uint16_t { return dq.getData().size(); }, [](DNSQuestion& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); }); - luaCtx.registerMember("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; }); - luaCtx.registerMember("tcp", [](const DNSQuestion& dq) -> bool { return dq.overTCP(); }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; }); - luaCtx.registerMember("skipCache", [](const DNSQuestion& dq) -> bool { return dq.ids.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.ids.skipCache = newSkipCache; }); - luaCtx.registerMember("pool", [](const DNSQuestion& dq) -> std::string { return dq.ids.poolName; }, [](DNSQuestion& dq, const std::string& newPoolName) { dq.ids.poolName = newPoolName; }); - luaCtx.registerMember("useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; }); - luaCtx.registerMember("ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; }); - luaCtx.registerMember("ecsPrefixLength", [](const DNSQuestion& dq) -> uint16_t { return dq.ecsPrefixLength; }, [](DNSQuestion& dq, uint16_t newPrefixLength) { dq.ecsPrefixLength = newPrefixLength; }); - luaCtx.registerMember (DNSQuestion::*)>("tempFailureTTL", - [](const DNSQuestion& dq) -> boost::optional { - return dq.ids.tempFailureTTL; - }, - [](DNSQuestion& dq, boost::optional newValue) { - dq.ids.tempFailureTTL = newValue; - } - ); - luaCtx.registerMember("deviceID", [](const DNSQuestion& dq) -> std::string { + luaCtx.registerMember( + "dh", [](const DNSQuestion& dq) -> dnsheader* { return dq.getMutableHeader(); }, [](DNSQuestion& dq, const dnsheader* dh) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [&dh](dnsheader& header) { + header = *dh; + return true; + }); }); + luaCtx.registerMember( + "len", [](const DNSQuestion& dq) -> uint16_t { return dq.getData().size(); }, [](DNSQuestion& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); }); + luaCtx.registerMember( + "opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void)newOpcode; }); + luaCtx.registerMember( + "tcp", [](const DNSQuestion& dq) -> bool { return dq.overTCP(); }, [](DNSQuestion& dq, bool newTcp) { (void)newTcp; }); + luaCtx.registerMember( + "skipCache", [](const DNSQuestion& dq) -> bool { return dq.ids.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.ids.skipCache = newSkipCache; }); + luaCtx.registerMember( + "pool", [](const DNSQuestion& dq) -> std::string { return dq.ids.poolName; }, [](DNSQuestion& dq, const std::string& newPoolName) { dq.ids.poolName = newPoolName; }); + luaCtx.registerMember( + "useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; }); + luaCtx.registerMember( + "ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; }); + luaCtx.registerMember( + "ecsPrefixLength", [](const DNSQuestion& dq) -> uint16_t { return dq.ecsPrefixLength; }, [](DNSQuestion& dq, uint16_t newPrefixLength) { dq.ecsPrefixLength = newPrefixLength; }); + luaCtx.registerMember(DNSQuestion::*)>( + "tempFailureTTL", + [](const DNSQuestion& dq) -> boost::optional { + return dq.ids.tempFailureTTL; + }, + [](DNSQuestion& dq, boost::optional newValue) { + dq.ids.tempFailureTTL = newValue; + }); + luaCtx.registerMember( + "deviceID", [](const DNSQuestion& dq) -> std::string { if (dq.ids.d_protoBufData) { return dq.ids.d_protoBufData->d_deviceID; } - return std::string(); - }, [](DNSQuestion& dq, const std::string& newValue) { + return std::string(); }, [](DNSQuestion& dq, const std::string& newValue) { if (!dq.ids.d_protoBufData) { dq.ids.d_protoBufData = std::make_unique(); } - dq.ids.d_protoBufData->d_deviceID = newValue; - }); - luaCtx.registerMember("deviceName", [](const DNSQuestion& dq) -> std::string { + dq.ids.d_protoBufData->d_deviceID = newValue; }); + luaCtx.registerMember( + "deviceName", [](const DNSQuestion& dq) -> std::string { if (dq.ids.d_protoBufData) { return dq.ids.d_protoBufData->d_deviceName; } - return std::string(); - }, [](DNSQuestion& dq, const std::string& newValue) { + return std::string(); }, [](DNSQuestion& dq, const std::string& newValue) { if (!dq.ids.d_protoBufData) { dq.ids.d_protoBufData = std::make_unique(); } - dq.ids.d_protoBufData->d_deviceName = newValue; - }); - luaCtx.registerMember("requestorID", [](const DNSQuestion& dq) -> std::string { + dq.ids.d_protoBufData->d_deviceName = newValue; }); + luaCtx.registerMember( + "requestorID", [](const DNSQuestion& dq) -> std::string { if (dq.ids.d_protoBufData) { return dq.ids.d_protoBufData->d_requestorID; } - return std::string(); - }, [](DNSQuestion& dq, const std::string& newValue) { + return std::string(); }, [](DNSQuestion& dq, const std::string& newValue) { if (!dq.ids.d_protoBufData) { dq.ids.d_protoBufData = std::make_unique(); } - dq.ids.d_protoBufData->d_requestorID = newValue; - }); - luaCtx.registerFunction("getDO", [](const DNSQuestion& dq) { + dq.ids.d_protoBufData->d_requestorID = newValue; }); + luaCtx.registerFunction("getDO", [](const DNSQuestion& dq) { return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO; - }); - luaCtx.registerFunction("getContent", [](const DNSQuestion& dq) { + }); + luaCtx.registerFunction("getContent", [](const DNSQuestion& dq) { return std::string(reinterpret_cast(dq.getData().data()), dq.getData().size()); }); - luaCtx.registerFunction("setContent", [](DNSQuestion& dq, const std::string& raw) { + luaCtx.registerFunction("setContent", [](DNSQuestion& dq, const std::string& raw) { uint16_t oldID = dq.getHeader()->id; auto& buffer = dq.getMutableData(); buffer.clear(); @@ -117,73 +125,73 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) return true; }); }); - luaCtx.registerFunction(DNSQuestion::*)()const>("getEDNSOptions", [](const DNSQuestion& dq) { + luaCtx.registerFunction (DNSQuestion::*)() const>("getEDNSOptions", [](const DNSQuestion& dq) { + if (dq.ednsOptions == nullptr) { + parseEDNSOptions(dq); if (dq.ednsOptions == nullptr) { - parseEDNSOptions(dq); - if (dq.ednsOptions == nullptr) { - throw std::runtime_error("parseEDNSOptions should have populated the EDNS options"); - } + throw std::runtime_error("parseEDNSOptions should have populated the EDNS options"); } + } - return *dq.ednsOptions; - }); - luaCtx.registerFunction("getTrailingData", [](const DNSQuestion& dq) { - return dq.getTrailingData(); - }); - luaCtx.registerFunction("setTrailingData", [](DNSQuestion& dq, const std::string& tail) { - return dq.setTrailingData(tail); - }); + return *dq.ednsOptions; + }); + luaCtx.registerFunction("getTrailingData", [](const DNSQuestion& dq) { + return dq.getTrailingData(); + }); + luaCtx.registerFunction("setTrailingData", [](DNSQuestion& dq, const std::string& tail) { + return dq.setTrailingData(tail); + }); - luaCtx.registerFunction("getServerNameIndication", [](const DNSQuestion& dq) { - return dq.sni; - }); + luaCtx.registerFunction("getServerNameIndication", [](const DNSQuestion& dq) { + return dq.sni; + }); - luaCtx.registerFunction("getProtocol", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getProtocol", [](const DNSQuestion& dq) { return dq.getProtocol().toPrettyString(); }); - luaCtx.registerFunction("getQueryTime", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getQueryTime", [](const DNSQuestion& dq) { return dq.ids.queryRealTime.getStartTime(); }); - luaCtx.registerFunction("sendTrap", [](const DNSQuestion& dq, boost::optional reason) { + luaCtx.registerFunction("sendTrap", [](const DNSQuestion& dq, boost::optional reason) { #ifdef HAVE_NET_SNMP - if (g_snmpAgent && g_snmpTrapsEnabled) { - g_snmpAgent->sendDNSTrap(dq, reason ? *reason : ""); - } + if (g_snmpAgent && g_snmpTrapsEnabled) { + g_snmpAgent->sendDNSTrap(dq, reason ? *reason : ""); + } #endif /* HAVE_NET_SNMP */ - }); + }); - luaCtx.registerFunction("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) { - dq.setTag(strLabel, strValue); - }); - luaCtx.registerFunction)>("setTagArray", [](DNSQuestion& dq, const LuaAssociativeTable&tags) { - for (const auto& tag : tags) { - dq.setTag(tag.first, tag.second); - } - }); - luaCtx.registerFunction("getTag", [](const DNSQuestion& dq, const std::string& strLabel) { - if (!dq.ids.qTag) { - return string(); - } + luaCtx.registerFunction("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) { + dq.setTag(strLabel, strValue); + }); + luaCtx.registerFunction)>("setTagArray", [](DNSQuestion& dq, const LuaAssociativeTable& tags) { + for (const auto& tag : tags) { + dq.setTag(tag.first, tag.second); + } + }); + luaCtx.registerFunction("getTag", [](const DNSQuestion& dq, const std::string& strLabel) { + if (!dq.ids.qTag) { + return string(); + } - std::string strValue; - const auto it = dq.ids.qTag->find(strLabel); - if (it == dq.ids.qTag->cend()) { - return string(); - } - return it->second; - }); - luaCtx.registerFunction("getTagArray", [](const DNSQuestion& dq) { - if (!dq.ids.qTag) { - QTag empty; - return empty; - } + std::string strValue; + const auto it = dq.ids.qTag->find(strLabel); + if (it == dq.ids.qTag->cend()) { + return string(); + } + return it->second; + }); + luaCtx.registerFunction("getTagArray", [](const DNSQuestion& dq) { + if (!dq.ids.qTag) { + QTag empty; + return empty; + } - return *dq.ids.qTag; - }); + return *dq.ids.qTag; + }); - luaCtx.registerFunction)>("setProxyProtocolValues", [](DNSQuestion& dq, const LuaArray& values) { + luaCtx.registerFunction)>("setProxyProtocolValues", [](DNSQuestion& dq, const LuaArray& values) { if (!dq.proxyProtocolValues) { dq.proxyProtocolValues = make_unique>(); } @@ -196,7 +204,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) } }); - luaCtx.registerFunction("addProxyProtocolValue", [](DNSQuestion& dq, uint64_t type, std::string value) { + luaCtx.registerFunction("addProxyProtocolValue", [](DNSQuestion& dq, uint64_t type, std::string value) { checkParameterBound("addProxyProtocolValue", type, std::numeric_limits::max()); if (!dq.proxyProtocolValues) { dq.proxyProtocolValues = make_unique>(); @@ -205,7 +213,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) dq.proxyProtocolValues->push_back({std::move(value), static_cast(type)}); }); - luaCtx.registerFunction(DNSQuestion::*)()>("getProxyProtocolValues", [](const DNSQuestion& dq) { + luaCtx.registerFunction (DNSQuestion::*)()>("getProxyProtocolValues", [](const DNSQuestion& dq) { LuaArray result; if (!dq.proxyProtocolValues) { return result; @@ -213,13 +221,13 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) result.resize(dq.proxyProtocolValues->size()); for (const auto& value : *dq.proxyProtocolValues) { - result.push_back({ value.type, value.content }); + result.push_back({value.type, value.content}); } return result; }); - luaCtx.registerFunction("changeName", [](DNSQuestion& dq, const DNSName& newName) -> bool { + luaCtx.registerFunction("changeName", [](DNSQuestion& dq, const DNSName& newName) -> bool { if (!dnsdist::changeNameInDNSPacket(dq.getMutableData(), dq.ids.qname, newName)) { return false; } @@ -227,38 +235,38 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) return true; }); - luaCtx.registerFunction, LuaArray>&, boost::optional)>("spoof", [](DNSQuestion& dnsQuestion, const boost::variant, LuaArray>& response, boost::optional typeForAny) { - if (response.type() == typeid(LuaArray)) { - std::vector data; - auto responses = boost::get>(response); - data.reserve(responses.size()); - for (const auto& resp : responses) { - data.push_back(resp.second); - } - std::string result; - SpoofAction tempSpoofAction(data); - tempSpoofAction(&dnsQuestion, &result); - return; + luaCtx.registerFunction, LuaArray>&, boost::optional)>("spoof", [](DNSQuestion& dnsQuestion, const boost::variant, LuaArray>& response, boost::optional typeForAny) { + if (response.type() == typeid(LuaArray)) { + std::vector data; + auto responses = boost::get>(response); + data.reserve(responses.size()); + for (const auto& resp : responses) { + data.push_back(resp.second); } - if (response.type() == typeid(LuaArray)) { - std::vector data; - auto responses = boost::get>(response); - data.reserve(responses.size()); - for (const auto& resp : responses) { - data.push_back(resp.second); - } - std::string result; - SpoofAction tempSpoofAction(data, typeForAny ? *typeForAny : std::optional()); - tempSpoofAction(&dnsQuestion, &result); - return; + std::string result; + SpoofAction tempSpoofAction(data); + tempSpoofAction(&dnsQuestion, &result); + return; + } + if (response.type() == typeid(LuaArray)) { + std::vector data; + auto responses = boost::get>(response); + data.reserve(responses.size()); + for (const auto& resp : responses) { + data.push_back(resp.second); } + std::string result; + SpoofAction tempSpoofAction(data, typeForAny ? *typeForAny : std::optional()); + tempSpoofAction(&dnsQuestion, &result); + return; + } }); - luaCtx.registerFunction("setEDNSOption", [](DNSQuestion& dq, uint16_t code, const std::string& data) { + luaCtx.registerFunction("setEDNSOption", [](DNSQuestion& dq, uint16_t code, const std::string& data) { setEDNSOption(dq, code, data); }); - luaCtx.registerFunction& extraText)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const boost::optional& extraText) { + luaCtx.registerFunction& extraText)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const boost::optional& extraText) { EDNSExtendedError ede; ede.infoCode = infoCode; if (extraText) { @@ -267,77 +275,78 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) dnsQuestion.ids.d_extendedError = std::make_unique(ede); }); - luaCtx.registerFunction("suspend", [](DNSQuestion& dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) { + luaCtx.registerFunction("suspend", [](DNSQuestion& dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) { dq.asynchronous = true; return dnsdist::suspendQuery(dq, asyncID, queryID, timeoutMs); }); - luaCtx.registerFunction("setRestartable", [](DNSQuestion& dq) { + luaCtx.registerFunction("setRestartable", [](DNSQuestion& dq) { dq.ids.d_packet = std::make_unique(dq.getData()); return true; }); -class AsynchronousObject -{ -public: - AsynchronousObject(std::unique_ptr&& obj_): object(std::move(obj_)) - { - } - - DNSQuestion getDQ() const + class AsynchronousObject { - return object->getDQ(); - } + public: + AsynchronousObject(std::unique_ptr&& obj_) : + object(std::move(obj_)) + { + } - DNSResponse getDR() const - { - return object->getDR(); - } + DNSQuestion getDQ() const + { + return object->getDQ(); + } - bool resume() - { - return dnsdist::queueQueryResumptionEvent(std::move(object)); - } + DNSResponse getDR() const + { + return object->getDR(); + } - bool drop() - { - auto sender = object->getTCPQuerySender(); - if (!sender) { - return false; + bool resume() + { + return dnsdist::queueQueryResumptionEvent(std::move(object)); } - struct timeval now; - gettimeofday(&now, nullptr); - sender->notifyIOError(now, TCPResponse(std::move(object->query))); - return true; - } + bool drop() + { + auto sender = object->getTCPQuerySender(); + if (!sender) { + return false; + } - bool setRCode(uint8_t rcode, bool clearAnswers) - { - return dnsdist::setInternalQueryRCode(object->query.d_idstate, object->query.d_buffer, rcode, clearAnswers); - } + struct timeval now; + gettimeofday(&now, nullptr); + sender->notifyIOError(now, TCPResponse(std::move(object->query))); + return true; + } -private: - std::unique_ptr object; -}; + bool setRCode(uint8_t rcode, bool clearAnswers) + { + return dnsdist::setInternalQueryRCode(object->query.d_idstate, object->query.d_buffer, rcode, clearAnswers); + } - luaCtx.registerFunction("getDQ", [](const AsynchronousObject& obj) { - return obj.getDQ(); - }); + private: + std::unique_ptr object; + }; - luaCtx.registerFunction("getDR", [](const AsynchronousObject& obj) { - return obj.getDR(); - }); + luaCtx.registerFunction("getDQ", [](const AsynchronousObject& obj) { + return obj.getDQ(); + }); - luaCtx.registerFunction("resume", [](AsynchronousObject& obj) { - return obj.resume(); - }); + luaCtx.registerFunction("getDR", [](const AsynchronousObject& obj) { + return obj.getDR(); + }); - luaCtx.registerFunction("drop", [](AsynchronousObject& obj) { - return obj.drop(); - }); + luaCtx.registerFunction("resume", [](AsynchronousObject& obj) { + return obj.resume(); + }); + + luaCtx.registerFunction("drop", [](AsynchronousObject& obj) { + return obj.drop(); + }); - luaCtx.registerFunction("setRCode", [](AsynchronousObject& obj, uint8_t rcode, bool clearAnswers) { + luaCtx.registerFunction("setRCode", [](AsynchronousObject& obj, uint8_t rcode, bool clearAnswers) { return obj.setRCode(rcode, clearAnswers); }); @@ -353,38 +362,46 @@ private: }); /* LuaWrapper doesn't support inheritance */ - luaCtx.registerMember("localaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origDest; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void) newLocal; }); - luaCtx.registerMember("qname", [](const DNSResponse& dq) -> const DNSName { return dq.ids.qname; }, [](DNSResponse& dq, const DNSName& newName) { (void) newName; }); - luaCtx.registerMember("qtype", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void) newType; }); - luaCtx.registerMember("qclass", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void) newClass; }); - luaCtx.registerMember("rcode", [](const DNSResponse& dq) -> int { return static_cast(dq.getHeader()->rcode); }, [](DNSResponse& dq, int newRCode) { - dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) { - header.rcode = static_cast(newRCode); - return true; - }); + luaCtx.registerMember( + "localaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origDest; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void)newLocal; }); + luaCtx.registerMember( + "qname", [](const DNSResponse& dq) -> const DNSName { return dq.ids.qname; }, [](DNSResponse& dq, const DNSName& newName) { (void)newName; }); + luaCtx.registerMember( + "qtype", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void)newType; }); + luaCtx.registerMember( + "qclass", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void)newClass; }); + luaCtx.registerMember( + "rcode", [](const DNSResponse& dq) -> int { return static_cast(dq.getHeader()->rcode); }, [](DNSResponse& dq, int newRCode) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) { + header.rcode = static_cast(newRCode); + return true; + }); }); + luaCtx.registerMember( + "remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void)newRemote; }); + luaCtx.registerMember( + "dh", [](const DNSResponse& dr) -> dnsheader* { return dr.getMutableHeader(); }, [](DNSResponse& dr, const dnsheader* dh) { dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [&dh](dnsheader& header) { + header = *dh; + return true; + }); }); + luaCtx.registerMember( + "len", [](const DNSResponse& dq) -> uint16_t { return dq.getData().size(); }, [](DNSResponse& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); }); + luaCtx.registerMember( + "opcode", [](const DNSResponse& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void)newOpcode; }); + luaCtx.registerMember( + "tcp", [](const DNSResponse& dq) -> bool { return dq.overTCP(); }, [](DNSResponse& dq, bool newTcp) { (void)newTcp; }); + luaCtx.registerMember( + "skipCache", [](const DNSResponse& dq) -> bool { return dq.ids.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.ids.skipCache = newSkipCache; }); + luaCtx.registerMember( + "pool", [](const DNSResponse& dq) -> std::string { return dq.ids.poolName; }, [](DNSResponse& dq, const std::string& newPoolName) { dq.ids.poolName = newPoolName; }); + luaCtx.registerFunction editFunc)>("editTTLs", [](DNSResponse& dr, std::function editFunc) { + editDNSPacketTTL(reinterpret_cast(dr.getMutableData().data()), dr.getData().size(), editFunc); }); - luaCtx.registerMember("remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void) newRemote; }); - luaCtx.registerMember("dh", [](const DNSResponse& dr) -> dnsheader* { return dr.getMutableHeader(); }, [](DNSResponse& dr, const dnsheader* dh) { - dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [&dh](dnsheader& header) { - header = *dh; - return true; - }); + luaCtx.registerFunction("getDO", [](const DNSResponse& dq) { + return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO; }); - luaCtx.registerMember("len", [](const DNSResponse& dq) -> uint16_t { return dq.getData().size(); }, [](DNSResponse& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); }); - luaCtx.registerMember("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; }); - luaCtx.registerMember("tcp", [](const DNSResponse& dq) -> bool { return dq.overTCP(); }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; }); - luaCtx.registerMember("skipCache", [](const DNSResponse& dq) -> bool { return dq.ids.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.ids.skipCache = newSkipCache; }); - luaCtx.registerMember("pool", [](const DNSResponse& dq) -> std::string { return dq.ids.poolName; }, [](DNSResponse& dq, const std::string& newPoolName) { dq.ids.poolName = newPoolName; }); - luaCtx.registerFunction editFunc)>("editTTLs", [](DNSResponse& dr, std::function editFunc) { - editDNSPacketTTL(reinterpret_cast(dr.getMutableData().data()), dr.getData().size(), editFunc); - }); - luaCtx.registerFunction("getDO", [](const DNSResponse& dq) { - return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO; - }); - luaCtx.registerFunction("getContent", [](const DNSResponse& dq) { + luaCtx.registerFunction("getContent", [](const DNSResponse& dq) { return std::string(reinterpret_cast(dq.getData().data()), dq.getData().size()); }); - luaCtx.registerFunction("setContent", [](DNSResponse& dr, const std::string& raw) { + luaCtx.registerFunction("setContent", [](DNSResponse& dr, const std::string& raw) { uint16_t oldID = dr.getHeader()->id; auto& buffer = dr.getMutableData(); buffer.clear(); @@ -395,127 +412,127 @@ private: }); }); - luaCtx.registerFunction(DNSResponse::*)()const>("getEDNSOptions", [](const DNSResponse& dq) { + luaCtx.registerFunction (DNSResponse::*)() const>("getEDNSOptions", [](const DNSResponse& dq) { + if (dq.ednsOptions == nullptr) { + parseEDNSOptions(dq); if (dq.ednsOptions == nullptr) { - parseEDNSOptions(dq); - if (dq.ednsOptions == nullptr) { - throw std::runtime_error("parseEDNSOptions should have populated the EDNS options"); - } + throw std::runtime_error("parseEDNSOptions should have populated the EDNS options"); } + } - return *dq.ednsOptions; - }); - luaCtx.registerFunction("getTrailingData", [](const DNSResponse& dq) { - return dq.getTrailingData(); - }); - luaCtx.registerFunction("setTrailingData", [](DNSResponse& dq, const std::string& tail) { - return dq.setTrailingData(tail); - }); + return *dq.ednsOptions; + }); + luaCtx.registerFunction("getTrailingData", [](const DNSResponse& dq) { + return dq.getTrailingData(); + }); + luaCtx.registerFunction("setTrailingData", [](DNSResponse& dq, const std::string& tail) { + return dq.setTrailingData(tail); + }); - luaCtx.registerFunction("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) { - dr.setTag(strLabel, strValue); - }); + luaCtx.registerFunction("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) { + dr.setTag(strLabel, strValue); + }); - luaCtx.registerFunction)>("setTagArray", [](DNSResponse& dr, const LuaAssociativeTable&tags) { - for (const auto& tag : tags) { - dr.setTag(tag.first, tag.second); - } - }); - luaCtx.registerFunction("getTag", [](const DNSResponse& dr, const std::string& strLabel) { - if (!dr.ids.qTag) { - return string(); - } + luaCtx.registerFunction)>("setTagArray", [](DNSResponse& dr, const LuaAssociativeTable& tags) { + for (const auto& tag : tags) { + dr.setTag(tag.first, tag.second); + } + }); + luaCtx.registerFunction("getTag", [](const DNSResponse& dr, const std::string& strLabel) { + if (!dr.ids.qTag) { + return string(); + } - std::string strValue; - const auto it = dr.ids.qTag->find(strLabel); - if (it == dr.ids.qTag->cend()) { - return string(); - } - return it->second; - }); - luaCtx.registerFunction("getTagArray", [](const DNSResponse& dr) { - if (!dr.ids.qTag) { - QTag empty; - return empty; - } + std::string strValue; + const auto it = dr.ids.qTag->find(strLabel); + if (it == dr.ids.qTag->cend()) { + return string(); + } + return it->second; + }); + luaCtx.registerFunction("getTagArray", [](const DNSResponse& dr) { + if (!dr.ids.qTag) { + QTag empty; + return empty; + } - return *dr.ids.qTag; - }); + return *dr.ids.qTag; + }); - luaCtx.registerFunction("getProtocol", [](const DNSResponse& dr) { + luaCtx.registerFunction("getProtocol", [](const DNSResponse& dr) { return dr.getProtocol().toPrettyString(); }); - luaCtx.registerFunction("getQueryTime", [](const DNSResponse& dr) { + luaCtx.registerFunction("getQueryTime", [](const DNSResponse& dr) { return dr.ids.queryRealTime.getStartTime(); }); - luaCtx.registerFunction("sendTrap", [](const DNSResponse& dr, boost::optional reason) { + luaCtx.registerFunction("sendTrap", [](const DNSResponse& dr, boost::optional reason) { #ifdef HAVE_NET_SNMP - if (g_snmpAgent && g_snmpTrapsEnabled) { - g_snmpAgent->sendDNSTrap(dr, reason ? *reason : ""); - } + if (g_snmpAgent && g_snmpTrapsEnabled) { + g_snmpAgent->sendDNSTrap(dr, reason ? *reason : ""); + } #endif /* HAVE_NET_SNMP */ - }); + }); #ifdef HAVE_DNS_OVER_HTTPS - luaCtx.registerFunction("getHTTPPath", [](const DNSQuestion& dq) { - if (dq.ids.du == nullptr) { - return std::string(); - } - return dq.ids.du->getHTTPPath(); - }); + luaCtx.registerFunction("getHTTPPath", [](const DNSQuestion& dq) { + if (dq.ids.du == nullptr) { + return std::string(); + } + return dq.ids.du->getHTTPPath(); + }); - luaCtx.registerFunction("getHTTPQueryString", [](const DNSQuestion& dq) { - if (dq.ids.du == nullptr) { - return std::string(); - } - return dq.ids.du->getHTTPQueryString(); - }); + luaCtx.registerFunction("getHTTPQueryString", [](const DNSQuestion& dq) { + if (dq.ids.du == nullptr) { + return std::string(); + } + return dq.ids.du->getHTTPQueryString(); + }); - luaCtx.registerFunction("getHTTPHost", [](const DNSQuestion& dq) { - if (dq.ids.du == nullptr) { - return std::string(); - } - return dq.ids.du->getHTTPHost(); - }); + luaCtx.registerFunction("getHTTPHost", [](const DNSQuestion& dq) { + if (dq.ids.du == nullptr) { + return std::string(); + } + return dq.ids.du->getHTTPHost(); + }); - luaCtx.registerFunction("getHTTPScheme", [](const DNSQuestion& dq) { - if (dq.ids.du == nullptr) { - return std::string(); - } - return dq.ids.du->getHTTPScheme(); - }); + luaCtx.registerFunction("getHTTPScheme", [](const DNSQuestion& dq) { + if (dq.ids.du == nullptr) { + return std::string(); + } + return dq.ids.du->getHTTPScheme(); + }); - luaCtx.registerFunction(DNSQuestion::*)(void)const>("getHTTPHeaders", [](const DNSQuestion& dq) { - if (dq.ids.du == nullptr) { - return LuaAssociativeTable(); - } - return dq.ids.du->getHTTPHeaders(); - }); + luaCtx.registerFunction (DNSQuestion::*)(void) const>("getHTTPHeaders", [](const DNSQuestion& dq) { + if (dq.ids.du == nullptr) { + return LuaAssociativeTable(); + } + return dq.ids.du->getHTTPHeaders(); + }); - luaCtx.registerFunction contentType)>("setHTTPResponse", [](DNSQuestion& dq, uint64_t statusCode, const std::string& body, const boost::optional contentType) { - if (dq.ids.du == nullptr) { - return; - } - checkParameterBound("DNSQuestion::setHTTPResponse", statusCode, std::numeric_limits::max()); - PacketBuffer vect(body.begin(), body.end()); - dq.ids.du->setHTTPResponse(statusCode, std::move(vect), contentType ? *contentType : ""); - }); + luaCtx.registerFunction contentType)>("setHTTPResponse", [](DNSQuestion& dq, uint64_t statusCode, const std::string& body, const boost::optional contentType) { + if (dq.ids.du == nullptr) { + return; + } + checkParameterBound("DNSQuestion::setHTTPResponse", statusCode, std::numeric_limits::max()); + PacketBuffer vect(body.begin(), body.end()); + dq.ids.du->setHTTPResponse(statusCode, std::move(vect), contentType ? *contentType : ""); + }); #endif /* HAVE_DNS_OVER_HTTPS */ - luaCtx.registerFunction("setNegativeAndAdditionalSOA", [](DNSQuestion& dq, bool nxd, const std::string& zone, uint64_t ttl, const std::string& mname, const std::string& rname, uint64_t serial, uint64_t refresh, uint64_t retry, uint64_t expire, uint64_t minimum) { - checkParameterBound("setNegativeAndAdditionalSOA", ttl, std::numeric_limits::max()); - checkParameterBound("setNegativeAndAdditionalSOA", serial, std::numeric_limits::max()); - checkParameterBound("setNegativeAndAdditionalSOA", refresh, std::numeric_limits::max()); - checkParameterBound("setNegativeAndAdditionalSOA", retry, std::numeric_limits::max()); - checkParameterBound("setNegativeAndAdditionalSOA", expire, std::numeric_limits::max()); - checkParameterBound("setNegativeAndAdditionalSOA", minimum, std::numeric_limits::max()); + luaCtx.registerFunction("setNegativeAndAdditionalSOA", [](DNSQuestion& dq, bool nxd, const std::string& zone, uint64_t ttl, const std::string& mname, const std::string& rname, uint64_t serial, uint64_t refresh, uint64_t retry, uint64_t expire, uint64_t minimum) { + checkParameterBound("setNegativeAndAdditionalSOA", ttl, std::numeric_limits::max()); + checkParameterBound("setNegativeAndAdditionalSOA", serial, std::numeric_limits::max()); + checkParameterBound("setNegativeAndAdditionalSOA", refresh, std::numeric_limits::max()); + checkParameterBound("setNegativeAndAdditionalSOA", retry, std::numeric_limits::max()); + checkParameterBound("setNegativeAndAdditionalSOA", expire, std::numeric_limits::max()); + checkParameterBound("setNegativeAndAdditionalSOA", minimum, std::numeric_limits::max()); - return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false); - }); + return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false); + }); - luaCtx.registerFunction& extraText)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const boost::optional& extraText) { + luaCtx.registerFunction& extraText)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const boost::optional& extraText) { EDNSExtendedError ede; ede.infoCode = infoCode; if (extraText) { @@ -524,12 +541,12 @@ private: dnsResponse.ids.d_extendedError = std::make_unique(ede); }); - luaCtx.registerFunction("suspend", [](DNSResponse& dr, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) { + luaCtx.registerFunction("suspend", [](DNSResponse& dr, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) { dr.asynchronous = true; return dnsdist::suspendResponse(dr, asyncID, queryID, timeoutMs); }); - luaCtx.registerFunction("changeName", [](DNSResponse& dr, const DNSName& newName) -> bool { + luaCtx.registerFunction("changeName", [](DNSResponse& dr, const DNSName& newName) -> bool { if (!dnsdist::changeNameInDNSPacket(dr.getMutableData(), dr.ids.qname, newName)) { return false; } @@ -537,7 +554,7 @@ private: return true; }); - luaCtx.registerFunction("restart", [](DNSResponse& dr) { + luaCtx.registerFunction("restart", [](DNSResponse& dr) { if (!dr.ids.d_packet) { return false; } @@ -547,7 +564,7 @@ private: return dnsdist::queueQueryResumptionEvent(std::move(query)); }); - luaCtx.registerFunction(DNSResponse::*)(void)const>("getSelectedBackend", [](const DNSResponse& dr) { + luaCtx.registerFunction (DNSResponse::*)(void) const>("getSelectedBackend", [](const DNSResponse& dr) { return dr.d_downstream; }); #endif /* DISABLE_NON_FFI_DQ_BINDINGS */ diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings.cc b/pdns/dnsdistdist/dnsdist-lua-bindings.cc index 3f5d6e2115..8f15f197ed 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings.cc @@ -35,40 +35,43 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) { luaCtx.writeFunction("vinfolog", [](const string& arg) { - vinfolog("%s", arg); - }); + vinfolog("%s", arg); + }); luaCtx.writeFunction("infolog", [](const string& arg) { - infolog("%s", arg); - }); + infolog("%s", arg); + }); luaCtx.writeFunction("errlog", [](const string& arg) { - errlog("%s", arg); - }); + errlog("%s", arg); + }); luaCtx.writeFunction("warnlog", [](const string& arg) { - warnlog("%s", arg); - }); + warnlog("%s", arg); + }); luaCtx.writeFunction("show", [](const string& arg) { - g_outputBuffer+=arg; - g_outputBuffer+="\n"; - }); + g_outputBuffer += arg; + g_outputBuffer += "\n"; + }); /* Exceptions */ - luaCtx.registerFunction("__tostring", [](const std::exception_ptr& eptr) -> std::string { - try { - if (eptr) { - std::rethrow_exception(eptr); - } - } catch(const std::exception& e) { - return string(e.what()); - } catch(const PDNSException& e) { - return e.reason; - } catch(...) { - return string("Unknown exception"); + luaCtx.registerFunction("__tostring", [](const std::exception_ptr& eptr) -> std::string { + try { + if (eptr) { + std::rethrow_exception(eptr); } - return string("No exception"); - }); + } + catch (const std::exception& e) { + return string(e.what()); + } + catch (const PDNSException& e) { + return e.reason; + } + catch (...) { + return string("Unknown exception"); + } + return string("No exception"); + }); #ifndef DISABLE_POLICIES_BINDINGS /* ServerPolicy */ - luaCtx.writeFunction("newServerPolicy", [](string name, ServerPolicy::policyfunc_t policy) { return std::make_shared(name, policy, true);}); + luaCtx.writeFunction("newServerPolicy", [](string name, ServerPolicy::policyfunc_t policy) { return std::make_shared(name, policy, true); }); luaCtx.registerMember("name", &ServerPolicy::d_name); luaCtx.registerMember("policy", &ServerPolicy::d_policy); luaCtx.registerMember("ffipolicy", &ServerPolicy::d_ffipolicy); @@ -84,8 +87,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) std::make_shared("wrandom", wrandom, false), std::make_shared("whashed", whashed, false), std::make_shared("chashed", chashed, false), - std::make_shared("leastOutstanding", leastOutstanding, false) - }; + std::make_shared("leastOutstanding", leastOutstanding, false)}; for (const auto& policy : policies) { luaCtx.writeVariable(policy->d_name, policy); } @@ -93,255 +95,257 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) #endif /* DISABLE_POLICIES_BINDINGS */ /* ServerPool */ - luaCtx.registerFunction::*)(std::shared_ptr)>("setCache", [](std::shared_ptr pool, std::shared_ptr cache) { - if (pool) { - pool->packetCache = std::move(cache); - } - }); + luaCtx.registerFunction::*)(std::shared_ptr)>("setCache", [](std::shared_ptr pool, std::shared_ptr cache) { + if (pool) { + pool->packetCache = std::move(cache); + } + }); luaCtx.registerFunction("getCache", &ServerPool::getCache); - luaCtx.registerFunction::*)()>("unsetCache", [](std::shared_ptr pool) { - if (pool) { - pool->packetCache = nullptr; - } - }); + luaCtx.registerFunction::*)()>("unsetCache", [](std::shared_ptr pool) { + if (pool) { + pool->packetCache = nullptr; + } + }); luaCtx.registerFunction("getECS", &ServerPool::getECS); luaCtx.registerFunction("setECS", &ServerPool::setECS); #ifndef DISABLE_DOWNSTREAM_BINDINGS /* DownstreamState */ - luaCtx.registerFunction("setQPS", [](DownstreamState& state, int lim) { state.qps = lim > 0 ? QPSLimiter(lim, lim) : QPSLimiter(); }); - luaCtx.registerFunction::*)(string)>("addPool", [](const std::shared_ptr& state, const string& pool) { - auto localPools = g_pools.getCopy(); - addServerToPool(localPools, pool, state); - g_pools.setState(localPools); - state->d_config.pools.insert(pool); - }); - luaCtx.registerFunction::*)(string)>("rmPool", [](const std::shared_ptr& state, const string& pool) { - auto localPools = g_pools.getCopy(); - removeServerFromPool(localPools, pool, state); - g_pools.setState(localPools); - state->d_config.pools.erase(pool); - }); - luaCtx.registerFunction("getOutstanding", [](const DownstreamState& state) { return state.outstanding.load(); }); - luaCtx.registerFunction("getDrops", [](const DownstreamState& state) { return state.reuseds.load(); }); - luaCtx.registerFunction("getLatency", [](const DownstreamState& state) { return state.getRelevantLatencyUsec(); }); + luaCtx.registerFunction("setQPS", [](DownstreamState& state, int lim) { state.qps = lim > 0 ? QPSLimiter(lim, lim) : QPSLimiter(); }); + luaCtx.registerFunction::*)(string)>("addPool", [](const std::shared_ptr& state, const string& pool) { + auto localPools = g_pools.getCopy(); + addServerToPool(localPools, pool, state); + g_pools.setState(localPools); + state->d_config.pools.insert(pool); + }); + luaCtx.registerFunction::*)(string)>("rmPool", [](const std::shared_ptr& state, const string& pool) { + auto localPools = g_pools.getCopy(); + removeServerFromPool(localPools, pool, state); + g_pools.setState(localPools); + state->d_config.pools.erase(pool); + }); + luaCtx.registerFunction("getOutstanding", [](const DownstreamState& state) { return state.outstanding.load(); }); + luaCtx.registerFunction("getDrops", [](const DownstreamState& state) { return state.reuseds.load(); }); + luaCtx.registerFunction("getLatency", [](const DownstreamState& state) { return state.getRelevantLatencyUsec(); }); luaCtx.registerFunction("isUp", &DownstreamState::isUp); luaCtx.registerFunction("setDown", &DownstreamState::setDown); luaCtx.registerFunction("setUp", &DownstreamState::setUp); - luaCtx.registerFunction newStatus)>("setAuto", [](DownstreamState& state, boost::optional newStatus) { - if (newStatus) { - state.setUpStatus(*newStatus); - } - state.setAuto(); - }); - luaCtx.registerFunction newStatus)>("setLazyAuto", [](DownstreamState& state, boost::optional newStatus) { - if (newStatus) { - state.setUpStatus(*newStatus); - } - state.setLazyAuto(); - }); - luaCtx.registerFunction("getName", [](const DownstreamState& state) -> const std::string& { return state.getName(); }); - luaCtx.registerFunction("getNameWithAddr", [](const DownstreamState& state) -> const std::string& { return state.getNameWithAddr(); }); + luaCtx.registerFunction newStatus)>("setAuto", [](DownstreamState& state, boost::optional newStatus) { + if (newStatus) { + state.setUpStatus(*newStatus); + } + state.setAuto(); + }); + luaCtx.registerFunction newStatus)>("setLazyAuto", [](DownstreamState& state, boost::optional newStatus) { + if (newStatus) { + state.setUpStatus(*newStatus); + } + state.setLazyAuto(); + }); + luaCtx.registerFunction("getName", [](const DownstreamState& state) -> const std::string& { return state.getName(); }); + luaCtx.registerFunction("getNameWithAddr", [](const DownstreamState& state) -> const std::string& { return state.getNameWithAddr(); }); luaCtx.registerMember("upStatus", &DownstreamState::upStatus); - luaCtx.registerMember("weight", - [](const DownstreamState& state) -> int {return state.d_config.d_weight;}, - [](DownstreamState& state, int newWeight) { state.setWeight(newWeight); } - ); - luaCtx.registerMember("order", - [](const DownstreamState& state) -> int {return state.d_config.order; }, - [](DownstreamState& state, int newOrder) { state.d_config.order = newOrder; } - ); - luaCtx.registerMember("name", [](const DownstreamState& backend) -> const std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); }); - luaCtx.registerFunction("getID", [](const DownstreamState& state) { return boost::uuids::to_string(*state.d_config.id); }); + luaCtx.registerMember( + "weight", + [](const DownstreamState& state) -> int { return state.d_config.d_weight; }, + [](DownstreamState& state, int newWeight) { state.setWeight(newWeight); }); + luaCtx.registerMember( + "order", + [](const DownstreamState& state) -> int { return state.d_config.order; }, + [](DownstreamState& state, int newOrder) { state.d_config.order = newOrder; }); + luaCtx.registerMember( + "name", [](const DownstreamState& backend) -> const std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); }); + luaCtx.registerFunction("getID", [](const DownstreamState& state) { return boost::uuids::to_string(*state.d_config.id); }); #endif /* DISABLE_DOWNSTREAM_BINDINGS */ #ifndef DISABLE_DNSHEADER_BINDINGS /* dnsheader */ - luaCtx.registerFunction("setRD", [](dnsheader& dh, bool v) { - dh.rd=v; - }); + luaCtx.registerFunction("setRD", [](dnsheader& dh, bool v) { + dh.rd = v; + }); - luaCtx.registerFunction("getRD", [](const dnsheader& dh) { - return (bool)dh.rd; - }); + luaCtx.registerFunction("getRD", [](const dnsheader& dh) { + return (bool)dh.rd; + }); - luaCtx.registerFunction("setRA", [](dnsheader& dh, bool v) { - dh.ra=v; - }); + luaCtx.registerFunction("setRA", [](dnsheader& dh, bool v) { + dh.ra = v; + }); - luaCtx.registerFunction("getRA", [](const dnsheader& dh) { - return (bool)dh.ra; - }); + luaCtx.registerFunction("getRA", [](const dnsheader& dh) { + return (bool)dh.ra; + }); - luaCtx.registerFunction("setAD", [](dnsheader& dh, bool v) { - dh.ad=v; - }); + luaCtx.registerFunction("setAD", [](dnsheader& dh, bool v) { + dh.ad = v; + }); - luaCtx.registerFunction("getAD", [](const dnsheader& dh) { - return (bool)dh.ad; - }); + luaCtx.registerFunction("getAD", [](const dnsheader& dh) { + return (bool)dh.ad; + }); - luaCtx.registerFunction("setAA", [](dnsheader& dh, bool v) { - dh.aa=v; - }); + luaCtx.registerFunction("setAA", [](dnsheader& dh, bool v) { + dh.aa = v; + }); - luaCtx.registerFunction("getAA", [](const dnsheader& dh) { - return (bool)dh.aa; - }); + luaCtx.registerFunction("getAA", [](const dnsheader& dh) { + return (bool)dh.aa; + }); - luaCtx.registerFunction("setCD", [](dnsheader& dh, bool v) { - dh.cd=v; - }); + luaCtx.registerFunction("setCD", [](dnsheader& dh, bool v) { + dh.cd = v; + }); - luaCtx.registerFunction("getCD", [](const dnsheader& dh) { - return (bool)dh.cd; - }); + luaCtx.registerFunction("getCD", [](const dnsheader& dh) { + return (bool)dh.cd; + }); - luaCtx.registerFunction("getID", [](const dnsheader& dh) { - return ntohs(dh.id); - }); + luaCtx.registerFunction("getID", [](const dnsheader& dh) { + return ntohs(dh.id); + }); - luaCtx.registerFunction("getTC", [](const dnsheader& dh) { - return (bool)dh.tc; - }); + luaCtx.registerFunction("getTC", [](const dnsheader& dh) { + return (bool)dh.tc; + }); - luaCtx.registerFunction("setTC", [](dnsheader& dh, bool v) { - dh.tc=v; - if(v) dh.ra = dh.rd; // you'll always need this, otherwise TC=1 gets ignored - }); + luaCtx.registerFunction("setTC", [](dnsheader& dh, bool v) { + dh.tc = v; + if (v) + dh.ra = dh.rd; // you'll always need this, otherwise TC=1 gets ignored + }); - luaCtx.registerFunction("setQR", [](dnsheader& dh, bool v) { - dh.qr=v; - }); + luaCtx.registerFunction("setQR", [](dnsheader& dh, bool v) { + dh.qr = v; + }); #endif /* DISABLE_DNSHEADER_BINDINGS */ #ifndef DISABLE_COMBO_ADDR_BINDINGS /* ComboAddress */ luaCtx.writeFunction("newCA", [](const std::string& name) { return ComboAddress(name); }); luaCtx.writeFunction("newCAFromRaw", [](const std::string& raw, boost::optional port) { - if (raw.size() == 4) { - struct sockaddr_in sin4; - memset(&sin4, 0, sizeof(sin4)); - sin4.sin_family = AF_INET; - memcpy(&sin4.sin_addr.s_addr, raw.c_str(), raw.size()); - if (port) { - sin4.sin_port = htons(*port); - } - return ComboAddress(&sin4); - } - else if (raw.size() == 16) { - struct sockaddr_in6 sin6; - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - memcpy(&sin6.sin6_addr.s6_addr, raw.c_str(), raw.size()); - if (port) { - sin6.sin6_port = htons(*port); - } - return ComboAddress(&sin6); - } - return ComboAddress(); - }); - luaCtx.registerFunction("tostring", [](const ComboAddress& ca) { return ca.toString(); }); - luaCtx.registerFunction("tostringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); - luaCtx.registerFunction("__tostring", [](const ComboAddress& ca) { return ca.toString(); }); - luaCtx.registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); - luaCtx.registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); - luaCtx.registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } ); - luaCtx.registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); - luaCtx.registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); - luaCtx.registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); - luaCtx.registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); - luaCtx.registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); - luaCtx.registerFunction("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); }); + if (raw.size() == 4) { + struct sockaddr_in sin4; + memset(&sin4, 0, sizeof(sin4)); + sin4.sin_family = AF_INET; + memcpy(&sin4.sin_addr.s_addr, raw.c_str(), raw.size()); + if (port) { + sin4.sin_port = htons(*port); + } + return ComboAddress(&sin4); + } + else if (raw.size() == 16) { + struct sockaddr_in6 sin6; + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr.s6_addr, raw.c_str(), raw.size()); + if (port) { + sin6.sin6_port = htons(*port); + } + return ComboAddress(&sin6); + } + return ComboAddress(); + }); + luaCtx.registerFunction("tostring", [](const ComboAddress& ca) { return ca.toString(); }); + luaCtx.registerFunction("tostringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + luaCtx.registerFunction("__tostring", [](const ComboAddress& ca) { return ca.toString(); }); + luaCtx.registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); + luaCtx.registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + luaCtx.registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); }); + luaCtx.registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); + luaCtx.registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); + luaCtx.registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); + luaCtx.registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); + luaCtx.registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); + luaCtx.registerFunction("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); }); #endif /* DISABLE_COMBO_ADDR_BINDINGS */ #ifndef DISABLE_DNSNAME_BINDINGS /* DNSName */ luaCtx.registerFunction("isPartOf", &DNSName::isPartOf); - luaCtx.registerFunction("chopOff", [](DNSName&dn ) { return dn.chopOff(); }); - luaCtx.registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); - luaCtx.registerFunction("hash", [](const DNSName& name) { return name.hash(); }); - luaCtx.registerFunction("wirelength", [](const DNSName& name) { return name.wirelength(); }); - luaCtx.registerFunction("tostring", [](const DNSName&dn ) { return dn.toString(); }); - luaCtx.registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); - luaCtx.registerFunction("toStringNoDot", [](const DNSName&dn ) { return dn.toStringNoDot(); }); - luaCtx.registerFunction("__tostring", [](const DNSName&dn ) { return dn.toString(); }); - luaCtx.registerFunction("toDNSString", [](const DNSName&dn ) { return dn.toDNSString(); }); - luaCtx.registerFunction("makeRelative", [](const DNSName& dn, const DNSName& to) { return dn.makeRelative(to); }); + luaCtx.registerFunction("chopOff", [](DNSName& dn) { return dn.chopOff(); }); + luaCtx.registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); + luaCtx.registerFunction("hash", [](const DNSName& name) { return name.hash(); }); + luaCtx.registerFunction("wirelength", [](const DNSName& name) { return name.wirelength(); }); + luaCtx.registerFunction("tostring", [](const DNSName& dn) { return dn.toString(); }); + luaCtx.registerFunction("toString", [](const DNSName& dn) { return dn.toString(); }); + luaCtx.registerFunction("toStringNoDot", [](const DNSName& dn) { return dn.toStringNoDot(); }); + luaCtx.registerFunction("__tostring", [](const DNSName& dn) { return dn.toString(); }); + luaCtx.registerFunction("toDNSString", [](const DNSName& dn) { return dn.toDNSString(); }); + luaCtx.registerFunction("makeRelative", [](const DNSName& dn, const DNSName& to) { return dn.makeRelative(to); }); luaCtx.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); }); luaCtx.writeFunction("newDNSNameFromRaw", [](const std::string& name) { return DNSName(name.c_str(), name.size(), 0, false); }); luaCtx.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); }); luaCtx.writeFunction("newDNSNameSet", []() { return DNSNameSet(); }); /* DNSNameSet */ - luaCtx.registerFunction("toString", [](const DNSNameSet&dns ) { return dns.toString(); }); - luaCtx.registerFunction("__tostring", [](const DNSNameSet&dns ) { return dns.toString(); }); - luaCtx.registerFunction("add", [](DNSNameSet& dns, DNSName& dn) { dns.insert(dn); }); - luaCtx.registerFunction("check", [](DNSNameSet& dns, DNSName& dn) { return dns.find(dn) != dns.end(); }); - luaCtx.registerFunction("delete",(size_t (DNSNameSet::*)(const DNSName&)) &DNSNameSet::erase); - luaCtx.registerFunction("size",(size_t (DNSNameSet::*)() const) &DNSNameSet::size); - luaCtx.registerFunction("clear",(void (DNSNameSet::*)()) &DNSNameSet::clear); - luaCtx.registerFunction("empty",(bool (DNSNameSet::*)() const) &DNSNameSet::empty); + luaCtx.registerFunction("toString", [](const DNSNameSet& dns) { return dns.toString(); }); + luaCtx.registerFunction("__tostring", [](const DNSNameSet& dns) { return dns.toString(); }); + luaCtx.registerFunction("add", [](DNSNameSet& dns, DNSName& dn) { dns.insert(dn); }); + luaCtx.registerFunction("check", [](DNSNameSet& dns, DNSName& dn) { return dns.find(dn) != dns.end(); }); + luaCtx.registerFunction("delete", (size_t(DNSNameSet::*)(const DNSName&)) & DNSNameSet::erase); + luaCtx.registerFunction("size", (size_t(DNSNameSet::*)() const) & DNSNameSet::size); + luaCtx.registerFunction("clear", (void(DNSNameSet::*)()) & DNSNameSet::clear); + luaCtx.registerFunction("empty", (bool(DNSNameSet::*)() const) & DNSNameSet::empty); #endif /* DISABLE_DNSNAME_BINDINGS */ #ifndef DISABLE_SUFFIX_MATCH_BINDINGS /* SuffixMatchNode */ - luaCtx.registerFunction, LuaArray> &name)>("add", [](SuffixMatchNode &smn, const boost::variant, LuaArray> &name) { - if (name.type() == typeid(DNSName)) { - const auto& actualName = boost::get(name); - smn.add(actualName); - return; - } - if (name.type() == typeid(std::string)) { - const auto& actualName = boost::get(name); - smn.add(actualName); - return; - } - if (name.type() == typeid(LuaArray)) { - const auto& names = boost::get>(name); - for (const auto& actualName : names) { - smn.add(actualName.second); - } - return; + luaCtx.registerFunction, LuaArray>& name)>("add", [](SuffixMatchNode& smn, const boost::variant, LuaArray>& name) { + if (name.type() == typeid(DNSName)) { + const auto& actualName = boost::get(name); + smn.add(actualName); + return; + } + if (name.type() == typeid(std::string)) { + const auto& actualName = boost::get(name); + smn.add(actualName); + return; + } + if (name.type() == typeid(LuaArray)) { + const auto& names = boost::get>(name); + for (const auto& actualName : names) { + smn.add(actualName.second); } - if (name.type() == typeid(LuaArray)) { - const auto& names = boost::get>(name); - for (const auto& actualName : names) { - smn.add(actualName.second); - } - return; + return; + } + if (name.type() == typeid(LuaArray)) { + const auto& names = boost::get>(name); + for (const auto& actualName : names) { + smn.add(actualName.second); } + return; + } }); - luaCtx.registerFunction, LuaArray> &name)>("remove", [](SuffixMatchNode &smn, const boost::variant, LuaArray> &name) { - if (name.type() == typeid(DNSName)) { - const auto& actualName = boost::get(name); - smn.remove(actualName); - return; - } - if (name.type() == typeid(string)) { - const auto& actualName = boost::get(name); - DNSName dnsName(actualName); - smn.remove(dnsName); - return; - } - if (name.type() == typeid(LuaArray)) { - const auto& names = boost::get>(name); - for (const auto& actualName : names) { - smn.remove(actualName.second); - } - return; + luaCtx.registerFunction, LuaArray>& name)>("remove", [](SuffixMatchNode& smn, const boost::variant, LuaArray>& name) { + if (name.type() == typeid(DNSName)) { + const auto& actualName = boost::get(name); + smn.remove(actualName); + return; + } + if (name.type() == typeid(string)) { + const auto& actualName = boost::get(name); + DNSName dnsName(actualName); + smn.remove(dnsName); + return; + } + if (name.type() == typeid(LuaArray)) { + const auto& names = boost::get>(name); + for (const auto& actualName : names) { + smn.remove(actualName.second); } - if (name.type() == typeid(LuaArray)) { - const auto& names = boost::get>(name); - for (const auto& actualName : names) { - DNSName dnsName(actualName.second); - smn.remove(dnsName); - } - return; + return; + } + if (name.type() == typeid(LuaArray)) { + const auto& names = boost::get>(name); + for (const auto& actualName : names) { + DNSName dnsName(actualName.second); + smn.remove(dnsName); } + return; + } }); - luaCtx.registerFunction("check", (bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check); + luaCtx.registerFunction("check", (bool(SuffixMatchNode::*)(const DNSName&) const) & SuffixMatchNode::check); luaCtx.registerFunction (SuffixMatchNode::*)(const DNSName&) const>("getBestMatch", [](const SuffixMatchNode& smn, const DNSName& needle) { boost::optional result{boost::none}; auto res = smn.getBestMatch(needle); @@ -354,7 +358,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) #ifndef DISABLE_NETMASK_BINDINGS /* Netmask */ - luaCtx.writeFunction("newNetmask", [](boost::variant addrOrStr, boost::optional bits) { + luaCtx.writeFunction("newNetmask", [](boost::variant addrOrStr, boost::optional bits) { if (addrOrStr.type() == typeid(ComboAddress)) { const auto& comboAddr = boost::get(addrOrStr); if (bits) { @@ -370,13 +374,13 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) }); luaCtx.registerFunction("empty", &Netmask::empty); luaCtx.registerFunction("getBits", &Netmask::getBits); - luaCtx.registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary - luaCtx.registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } ); + luaCtx.registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); }); // const reference makes this necessary + luaCtx.registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); }); luaCtx.registerFunction("isIpv4", &Netmask::isIPv4); luaCtx.registerFunction("isIPv4", &Netmask::isIPv4); luaCtx.registerFunction("isIpv6", &Netmask::isIPv6); luaCtx.registerFunction("isIPv6", &Netmask::isIPv6); - luaCtx.registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match); + luaCtx.registerFunction("match", (bool(Netmask::*)(const string&) const) & Netmask::match); luaCtx.registerFunction("toString", &Netmask::toString); luaCtx.registerFunction("__tostring", &Netmask::toString); luaCtx.registerEqFunction(&Netmask::operator==); @@ -384,29 +388,27 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) /* NetmaskGroup */ luaCtx.writeFunction("newNMG", []() { return NetmaskGroup(); }); - luaCtx.registerFunction("addMask", [](NetmaskGroup& nmg, const std::string& mask) - { - nmg.addMask(mask); - }); - luaCtx.registerFunction("addNMG", [](NetmaskGroup& nmg, const NetmaskGroup& otherNMG) { + luaCtx.registerFunction("addMask", [](NetmaskGroup& nmg, const std::string& mask) { + nmg.addMask(mask); + }); + luaCtx.registerFunction("addNMG", [](NetmaskGroup& nmg, const NetmaskGroup& otherNMG) { /* this is not going to be very efficient, sorry */ auto entries = otherNMG.toStringVector(); for (const auto& entry : entries) { nmg.addMask(entry); } }); - luaCtx.registerFunction& map)>("addMasks", [](NetmaskGroup&nmg, const std::map& map) - { - for (const auto& entry : map) { - nmg.addMask(Netmask(entry.first)); - } - }); + luaCtx.registerFunction& map)>("addMasks", [](NetmaskGroup& nmg, const std::map& map) { + for (const auto& entry : map) { + nmg.addMask(Netmask(entry.first)); + } + }); - luaCtx.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); + luaCtx.registerFunction("match", (bool(NetmaskGroup::*)(const ComboAddress&) const) & NetmaskGroup::match); luaCtx.registerFunction("size", &NetmaskGroup::size); luaCtx.registerFunction("clear", &NetmaskGroup::clear); - luaCtx.registerFunction("toString", [](const NetmaskGroup& nmg ) { return "NetmaskGroup " + nmg.toString(); }); - luaCtx.registerFunction("__tostring", [](const NetmaskGroup& nmg ) { return "NetmaskGroup " + nmg.toString(); }); + luaCtx.registerFunction("toString", [](const NetmaskGroup& nmg) { return "NetmaskGroup " + nmg.toString(); }); + luaCtx.registerFunction("__tostring", [](const NetmaskGroup& nmg) { return "NetmaskGroup " + nmg.toString(); }); #endif /* DISABLE_NETMASK_BINDINGS */ #ifndef DISABLE_QPS_LIMITER_BINDINGS @@ -417,48 +419,48 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) #ifndef DISABLE_CLIENT_STATE_BINDINGS /* ClientState */ - luaCtx.registerFunction("toString", [](const ClientState& fe) { - setLuaNoSideEffect(); - return fe.local.toStringWithPort(); - }); - luaCtx.registerFunction("__tostring", [](const ClientState& fe) { - setLuaNoSideEffect(); - return fe.local.toStringWithPort(); - }); - luaCtx.registerFunction("getType", [](const ClientState& fe) { - setLuaNoSideEffect(); - return fe.getType(); - }); - luaCtx.registerFunction("getConfiguredTLSProvider", [](const ClientState& fe) { - setLuaNoSideEffect(); - if (fe.tlsFrontend != nullptr) { - return fe.tlsFrontend->getRequestedProvider(); - } - else if (fe.dohFrontend != nullptr) { - return std::string("openssl"); - } - return std::string(); + luaCtx.registerFunction("toString", [](const ClientState& fe) { + setLuaNoSideEffect(); + return fe.local.toStringWithPort(); }); - luaCtx.registerFunction("getEffectiveTLSProvider", [](const ClientState& fe) { - setLuaNoSideEffect(); - if (fe.tlsFrontend != nullptr) { - return fe.tlsFrontend->getEffectiveProvider(); - } - else if (fe.dohFrontend != nullptr) { - return std::string("openssl"); - } - return std::string(); + luaCtx.registerFunction("__tostring", [](const ClientState& fe) { + setLuaNoSideEffect(); + return fe.local.toStringWithPort(); + }); + luaCtx.registerFunction("getType", [](const ClientState& fe) { + setLuaNoSideEffect(); + return fe.getType(); + }); + luaCtx.registerFunction("getConfiguredTLSProvider", [](const ClientState& fe) { + setLuaNoSideEffect(); + if (fe.tlsFrontend != nullptr) { + return fe.tlsFrontend->getRequestedProvider(); + } + else if (fe.dohFrontend != nullptr) { + return std::string("openssl"); + } + return std::string(); + }); + luaCtx.registerFunction("getEffectiveTLSProvider", [](const ClientState& fe) { + setLuaNoSideEffect(); + if (fe.tlsFrontend != nullptr) { + return fe.tlsFrontend->getEffectiveProvider(); + } + else if (fe.dohFrontend != nullptr) { + return std::string("openssl"); + } + return std::string(); }); luaCtx.registerMember("muted", &ClientState::muted); #ifdef HAVE_EBPF - luaCtx.registerFunction)>("attachFilter", [](ClientState& frontend, std::shared_ptr bpf) { - if (bpf) { - frontend.attachFilter(bpf, frontend.getSocket()); - } - }); - luaCtx.registerFunction("detachFilter", [](ClientState& frontend) { - frontend.detachFilter(frontend.getSocket()); - }); + luaCtx.registerFunction)>("attachFilter", [](ClientState& frontend, std::shared_ptr bpf) { + if (bpf) { + frontend.attachFilter(bpf, frontend.getSocket()); + } + }); + luaCtx.registerFunction("detachFilter", [](ClientState& frontend) { + frontend.detachFilter(frontend.getSocket()); + }); #endif /* HAVE_EBPF */ #endif /* DISABLE_CLIENT_STATE_BINDINGS */ @@ -466,80 +468,80 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) #ifdef HAVE_EBPF using bpfopts_t = LuaAssociativeTable>; luaCtx.writeFunction("newBPFFilter", [client](bpfopts_t opts) { - if (client) { - return std::shared_ptr(nullptr); - } - std::unordered_map mapsConfig; - - const auto convertParamsToConfig = [&](const std::string& name, BPFFilter::MapType type) { - BPFFilter::MapConfiguration config; - config.d_type = type; - if (const string key = name + "MaxItems"; opts.count(key)) { - const auto& tmp = opts.at(key); - if (tmp.type() != typeid(uint32_t)) { - throw std::runtime_error("params is invalid"); - } - const auto& params = boost::get(tmp); - config.d_maxItems = params; + if (client) { + return std::shared_ptr(nullptr); + } + std::unordered_map mapsConfig; + + const auto convertParamsToConfig = [&](const std::string& name, BPFFilter::MapType type) { + BPFFilter::MapConfiguration config; + config.d_type = type; + if (const string key = name + "MaxItems"; opts.count(key)) { + const auto& tmp = opts.at(key); + if (tmp.type() != typeid(uint32_t)) { + throw std::runtime_error("params is invalid"); } + const auto& params = boost::get(tmp); + config.d_maxItems = params; + } - if (const string key = name + "PinnedPath"; opts.count(key)) { - auto& tmp = opts.at(key); - if (tmp.type() != typeid(string)) { - throw std::runtime_error("params is invalid"); - } - auto& params = boost::get(tmp); - config.d_pinnedPath = std::move(params); - } - mapsConfig[name] = std::move(config); - }; - - convertParamsToConfig("ipv4", BPFFilter::MapType::IPv4); - convertParamsToConfig("ipv6", BPFFilter::MapType::IPv6); - convertParamsToConfig("qnames", BPFFilter::MapType::QNames); - convertParamsToConfig("cidr4", BPFFilter::MapType::CIDR4); - convertParamsToConfig("cidr6", BPFFilter::MapType::CIDR6); - - BPFFilter::MapFormat format = BPFFilter::MapFormat::Legacy; - bool external = false; - if (opts.count("external")) { - const auto& tmp = opts.at("external"); - if (tmp.type() != typeid(bool)) { + if (const string key = name + "PinnedPath"; opts.count(key)) { + auto& tmp = opts.at(key); + if (tmp.type() != typeid(string)) { throw std::runtime_error("params is invalid"); } - if ((external = boost::get(tmp))) { - format = BPFFilter::MapFormat::WithActions; - } + auto& params = boost::get(tmp); + config.d_pinnedPath = std::move(params); + } + mapsConfig[name] = std::move(config); + }; + + convertParamsToConfig("ipv4", BPFFilter::MapType::IPv4); + convertParamsToConfig("ipv6", BPFFilter::MapType::IPv6); + convertParamsToConfig("qnames", BPFFilter::MapType::QNames); + convertParamsToConfig("cidr4", BPFFilter::MapType::CIDR4); + convertParamsToConfig("cidr6", BPFFilter::MapType::CIDR6); + + BPFFilter::MapFormat format = BPFFilter::MapFormat::Legacy; + bool external = false; + if (opts.count("external")) { + const auto& tmp = opts.at("external"); + if (tmp.type() != typeid(bool)) { + throw std::runtime_error("params is invalid"); + } + if ((external = boost::get(tmp))) { + format = BPFFilter::MapFormat::WithActions; } + } - return std::make_shared(mapsConfig, format, external); + return std::make_shared(mapsConfig, format, external); }); - luaCtx.registerFunction::*)(const ComboAddress& ca, boost::optional action)>("block", [](std::shared_ptr bpf, const ComboAddress& ca, boost::optional action) { - if (bpf) { - if (!action) { - return bpf->block(ca, BPFFilter::MatchAction::Drop); - } - else { - BPFFilter::MatchAction match; - - switch (*action) { - case 0: - match = BPFFilter::MatchAction::Pass; - break; - case 1: - match = BPFFilter::MatchAction::Drop; - break; - case 2: - match = BPFFilter::MatchAction::Truncate; - break; - default: - throw std::runtime_error("Unsupported action for BPFFilter::block"); - } - return bpf->block(ca, match); + luaCtx.registerFunction::*)(const ComboAddress& ca, boost::optional action)>("block", [](std::shared_ptr bpf, const ComboAddress& ca, boost::optional action) { + if (bpf) { + if (!action) { + return bpf->block(ca, BPFFilter::MatchAction::Drop); + } + else { + BPFFilter::MatchAction match; + + switch (*action) { + case 0: + match = BPFFilter::MatchAction::Pass; + break; + case 1: + match = BPFFilter::MatchAction::Drop; + break; + case 2: + match = BPFFilter::MatchAction::Truncate; + break; + default: + throw std::runtime_error("Unsupported action for BPFFilter::block"); } + return bpf->block(ca, match); } - }); + } + }); luaCtx.registerFunction::*)(const string& range, uint32_t action, boost::optional force)>("addRangeRule", [](std::shared_ptr bpf, const string& range, uint32_t action, boost::optional force) { if (!bpf) { return; @@ -560,37 +562,37 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) } return bpf->addRangeRule(Netmask(range), force ? *force : false, match); }); - luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype, boost::optional action)>("blockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype, boost::optional action) { - if (bpf) { - if (!action) { - return bpf->block(qname, BPFFilter::MatchAction::Drop, qtype ? *qtype : 255); - } - else { - BPFFilter::MatchAction match; - - switch (*action) { - case 0: - match = BPFFilter::MatchAction::Pass; - break; - case 1: - match = BPFFilter::MatchAction::Drop; - break; - case 2: - match = BPFFilter::MatchAction::Truncate; - break; - default: - throw std::runtime_error("Unsupported action for BPFFilter::blockQName"); - } - return bpf->block(qname, match, qtype ? *qtype : 255); + luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype, boost::optional action)>("blockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype, boost::optional action) { + if (bpf) { + if (!action) { + return bpf->block(qname, BPFFilter::MatchAction::Drop, qtype ? *qtype : 255); + } + else { + BPFFilter::MatchAction match; + + switch (*action) { + case 0: + match = BPFFilter::MatchAction::Pass; + break; + case 1: + match = BPFFilter::MatchAction::Drop; + break; + case 2: + match = BPFFilter::MatchAction::Truncate; + break; + default: + throw std::runtime_error("Unsupported action for BPFFilter::blockQName"); } + return bpf->block(qname, match, qtype ? *qtype : 255); } - }); + } + }); - luaCtx.registerFunction::*)(const ComboAddress& ca)>("unblock", [](std::shared_ptr bpf, const ComboAddress& ca) { - if (bpf) { - return bpf->unblock(ca); - } - }); + luaCtx.registerFunction::*)(const ComboAddress& ca)>("unblock", [](std::shared_ptr bpf, const ComboAddress& ca) { + if (bpf) { + return bpf->unblock(ca); + } + }); luaCtx.registerFunction::*)(const string& range)>("rmRangeRule", [](std::shared_ptr bpf, const string& range) { if (!bpf) { return; @@ -614,108 +616,108 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) } return res; }); - luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("unblockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { - if (bpf) { - return bpf->unblock(qname, qtype ? *qtype : 255); - } - }); + luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("unblockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { + if (bpf) { + return bpf->unblock(qname, qtype ? *qtype : 255); + } + }); - luaCtx.registerFunction::*)()const>("getStats", [](const std::shared_ptr bpf) { - setLuaNoSideEffect(); - std::string res; - if (bpf) { - auto stats = bpf->getAddrStats(); - for (const auto& value : stats) { - if (value.first.sin4.sin_family == AF_INET) { - res += value.first.toString() + ": " + std::to_string(value.second) + "\n"; - } - else if (value.first.sin4.sin_family == AF_INET6) { - res += "[" + value.first.toString() + "]: " + std::to_string(value.second) + "\n"; - } + luaCtx.registerFunction::*)() const>("getStats", [](const std::shared_ptr bpf) { + setLuaNoSideEffect(); + std::string res; + if (bpf) { + auto stats = bpf->getAddrStats(); + for (const auto& value : stats) { + if (value.first.sin4.sin_family == AF_INET) { + res += value.first.toString() + ": " + std::to_string(value.second) + "\n"; } - const auto rangeStat = bpf->getRangeRule(); - for (const auto& value : rangeStat) { - if (value.first.isIPv4()) { - res += BPFFilter::toString(value.second.action) + "\t " + value.first.toString() + ": " + std::to_string(value.second.counter) + "\n"; - } - else if (value.first.isIPv6()) { - res += BPFFilter::toString(value.second.action) + "\t[" + value.first.toString() + "]: " + std::to_string(value.second.counter) + "\n"; - } + else if (value.first.sin4.sin_family == AF_INET6) { + res += "[" + value.first.toString() + "]: " + std::to_string(value.second) + "\n"; } - auto qstats = bpf->getQNameStats(); - for (const auto& value : qstats) { - res += std::get<0>(value).toString() + " " + std::to_string(std::get<1>(value)) + ": " + std::to_string(std::get<2>(value)) + "\n"; + } + const auto rangeStat = bpf->getRangeRule(); + for (const auto& value : rangeStat) { + if (value.first.isIPv4()) { + res += BPFFilter::toString(value.second.action) + "\t " + value.first.toString() + ": " + std::to_string(value.second.counter) + "\n"; + } + else if (value.first.isIPv6()) { + res += BPFFilter::toString(value.second.action) + "\t[" + value.first.toString() + "]: " + std::to_string(value.second.counter) + "\n"; } } - return res; - }); - - luaCtx.registerFunction::*)()>("attachToAllBinds", [](std::shared_ptr bpf) { - std::string res; - if (!g_configurationDone) { - throw std::runtime_error("attachToAllBinds() cannot be used at configuration time!"); - return; + auto qstats = bpf->getQNameStats(); + for (const auto& value : qstats) { + res += std::get<0>(value).toString() + " " + std::to_string(std::get<1>(value)) + ": " + std::to_string(std::get<2>(value)) + "\n"; } - if (bpf) { - for (const auto& frontend : g_frontends) { - frontend->attachFilter(bpf, frontend->getSocket()); - } + } + return res; + }); + + luaCtx.registerFunction::*)()>("attachToAllBinds", [](std::shared_ptr bpf) { + std::string res; + if (!g_configurationDone) { + throw std::runtime_error("attachToAllBinds() cannot be used at configuration time!"); + return; + } + if (bpf) { + for (const auto& frontend : g_frontends) { + frontend->attachFilter(bpf, frontend->getSocket()); } - }); + } + }); - luaCtx.writeFunction("newDynBPFFilter", [client](std::shared_ptr bpf) { - if (client) { - return std::shared_ptr(nullptr); - } - return std::make_shared(bpf); - }); - - luaCtx.registerFunction::*)(const ComboAddress& addr, boost::optional seconds)>("block", [](std::shared_ptr dbpf, const ComboAddress& addr, boost::optional seconds) { - if (dbpf) { - struct timespec until; - clock_gettime(CLOCK_MONOTONIC, &until); - until.tv_sec += seconds ? *seconds : 10; - dbpf->block(addr, until); - } - }); + luaCtx.writeFunction("newDynBPFFilter", [client](std::shared_ptr bpf) { + if (client) { + return std::shared_ptr(nullptr); + } + return std::make_shared(bpf); + }); - luaCtx.registerFunction::*)()>("purgeExpired", [](std::shared_ptr dbpf) { - if (dbpf) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - dbpf->purgeExpired(now); - } - }); + luaCtx.registerFunction::*)(const ComboAddress& addr, boost::optional seconds)>("block", [](std::shared_ptr dbpf, const ComboAddress& addr, boost::optional seconds) { + if (dbpf) { + struct timespec until; + clock_gettime(CLOCK_MONOTONIC, &until); + until.tv_sec += seconds ? *seconds : 10; + dbpf->block(addr, until); + } + }); - luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("excludeRange", [](std::shared_ptr dbpf, LuaTypeOrArrayOf ranges) { - if (!dbpf) { - return; - } + luaCtx.registerFunction::*)()>("purgeExpired", [](std::shared_ptr dbpf) { + if (dbpf) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + dbpf->purgeExpired(now); + } + }); - if (ranges.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&ranges)) { - dbpf->excludeRange(Netmask(range.second)); - } - } - else { - dbpf->excludeRange(Netmask(*boost::get(&ranges))); - } - }); + luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("excludeRange", [](std::shared_ptr dbpf, LuaTypeOrArrayOf ranges) { + if (!dbpf) { + return; + } - luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("includeRange", [](std::shared_ptr dbpf, LuaTypeOrArrayOf ranges) { - if (!dbpf) { - return; + if (ranges.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&ranges)) { + dbpf->excludeRange(Netmask(range.second)); } + } + else { + dbpf->excludeRange(Netmask(*boost::get(&ranges))); + } + }); - if (ranges.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&ranges)) { - dbpf->includeRange(Netmask(range.second)); - } - } - else { - dbpf->includeRange(Netmask(*boost::get(&ranges))); + luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("includeRange", [](std::shared_ptr dbpf, LuaTypeOrArrayOf ranges) { + if (!dbpf) { + return; + } + + if (ranges.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&ranges)) { + dbpf->includeRange(Netmask(range.second)); } - }); + } + else { + dbpf->includeRange(Netmask(*boost::get(&ranges))); + } + }); #endif /* HAVE_EBPF */ #ifdef HAVE_XSK using xskopt_t = LuaAssociativeTable>; @@ -752,7 +754,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) dnsdist::xsk::g_xsk.push_back(socket); return socket; }); - luaCtx.registerFunction::*)()const>("getMetrics", [](const std::shared_ptr& xsk) -> std::string { + luaCtx.registerFunction::*)() const>("getMetrics", [](const std::shared_ptr& xsk) -> std::string { if (!xsk) { return {}; } @@ -760,10 +762,10 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) }); #endif /* HAVE_XSK */ /* EDNSOptionView */ - luaCtx.registerFunction("count", [](const EDNSOptionView& option) { - return option.values.size(); - }); - luaCtx.registerFunction(EDNSOptionView::*)()const>("getValues", [] (const EDNSOptionView& option) { + luaCtx.registerFunction("count", [](const EDNSOptionView& option) { + return option.values.size(); + }); + luaCtx.registerFunction (EDNSOptionView::*)() const>("getValues", [](const EDNSOptionView& option) { std::vector values; for (const auto& value : option.values) { values.push_back(std::string(value.content, value.size)); @@ -783,8 +785,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) return std::make_shared(regex, status, PacketBuffer(content.begin(), content.end()), headers); }); - luaCtx.writeFunction("newSVCRecordParameters", [](uint64_t priority, const std::string& target, boost::optional additionalParameters) - { + luaCtx.writeFunction("newSVCRecordParameters", [](uint64_t priority, const std::string& target, boost::optional additionalParameters) { checkParameterBound("newSVCRecordParameters", priority, std::numeric_limits::max()); SVCRecordParameters parameters; if (additionalParameters) { @@ -842,7 +843,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) if (client || configCheck) { return; } - std::thread newThread(dnsdist::resolver::asynchronousResolver, std::move(hostname), [callback=std::move(callback)](const std::string& resolvedHostname, std::vector& ips) { + std::thread newThread(dnsdist::resolver::asynchronousResolver, std::move(hostname), [callback = std::move(callback)](const std::string& resolvedHostname, std::vector& ips) { LuaArray result; result.reserve(ips.size()); for (const auto& entry : ips) { diff --git a/pdns/dnsdistdist/dnsdist-lua-inspection.cc b/pdns/dnsdistdist/dnsdist-lua-inspection.cc index 35b5c8b9b3..304a05af5d 100644 --- a/pdns/dnsdistdist/dnsdist-lua-inspection.cc +++ b/pdns/dnsdistdist/dnsdist-lua-inspection.cc @@ -31,17 +31,17 @@ #include "statnode.hh" #ifndef DISABLE_TOP_N_BINDINGS -static LuaArray>> getGenResponses(uint64_t top, boost::optional labels, std::function pred) +static LuaArray>> getGenResponses(uint64_t top, boost::optional labels, std::function pred) { setLuaNoSideEffect(); map counts; - unsigned int total=0; + unsigned int total = 0; { for (const auto& shard : g_rings.d_shards) { auto rl = shard->respRing.lock(); if (!labels) { - for(const auto& a : *rl) { - if(!pred(a)) + for (const auto& a : *rl) { + if (!pred(a)) continue; counts[a.name]++; total++; @@ -49,8 +49,8 @@ static LuaArray>> getGenResponses(uint } else { unsigned int lab = *labels; - for(const auto& a : *rl) { - if(!pred(a)) + for (const auto& a : *rl) { + if (!pred(a)) continue; DNSName temp(a.name); @@ -67,29 +67,28 @@ static LuaArray>> getGenResponses(uint for (const auto& c : counts) rcounts.emplace_back(c.second, c.first.makeLowerCase()); - sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, - const decltype(rcounts)::value_type& b) { - return b.first < a.first; - }); + sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, const decltype(rcounts)::value_type& b) { + return b.first < a.first; + }); - LuaArray>> ret; + LuaArray>> ret; ret.reserve(std::min(rcounts.size(), static_cast(top + 1U))); int count = 1; unsigned int rest = 0; for (const auto& rc : rcounts) { if (count == static_cast(top + 1)) { - rest+=rc.first; + rest += rc.first; } else { - ret.push_back({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); + ret.push_back({count++, {rc.second.toString(), rc.first, 100.0 * rc.first / total}}); } } if (total > 0) { - ret.push_back({count, {"Rest", rest, 100.0*rest/total}}); + ret.push_back({count, {"Rest", rest, 100.0 * rest / total}}); } else { - ret.push_back({count, {"Rest", rest, 100.0 }}); + ret.push_back({count, {"Rest", rest, 100.0}}); } return ret; @@ -102,12 +101,12 @@ static LuaArray>> getGenResponses(uint typedef std::unordered_map counts_t; static counts_t filterScore(const counts_t& counts, - double delta, unsigned int rate) + double delta, unsigned int rate) { counts_t ret; - double lim = delta*rate; - for(const auto& c : counts) { + double lim = delta * rate; + for (const auto& c : counts) { if (c.second > lim) { ret[c.first] = c.second; } @@ -129,8 +128,8 @@ static void statNodeRespRing(statvisitor_t visitor, uint64_t seconds) for (const auto& shard : g_rings.d_shards) { auto rl = shard->respRing.lock(); - for(const auto& c : *rl) { - if (now < c.when){ + for (const auto& c : *rl) { + if (now < c.when) { continue; } @@ -144,8 +143,7 @@ static void statNodeRespRing(statvisitor_t visitor, uint64_t seconds) } StatNode::Stat node; - root.visit([visitor = std::move(visitor)](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { - visitor(*node_, self, children);}, node); + root.visit([visitor = std::move(visitor)](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { visitor(*node_, self, children); }, node); } static LuaArray> getRespRing(boost::optional rcode) @@ -184,15 +182,15 @@ static counts_t exceedRespGen(unsigned int rate, int seconds, std::functionrespRing.lock(); - for(const auto& c : *rl) { + for (const auto& c : *rl) { - if(seconds && c.when < cutoff) + if (seconds && c.when < cutoff) continue; - if(now < c.when) + if (now < c.when) continue; T(counts, c); - if(c.when < mintime) + if (c.when < mintime) mintime = c.when; } } @@ -213,13 +211,13 @@ static counts_t exceedQueryGen(unsigned int rate, int seconds, std::functionqueryRing.lock(); - for(const auto& c : *rl) { - if(seconds && c.when < cutoff) + for (const auto& c : *rl) { + if (seconds && c.when < cutoff) continue; - if(now < c.when) + if (now < c.when) continue; T(counts, c); - if(c.when < mintime) + if (c.when < mintime) mintime = c.when; } } @@ -228,22 +226,19 @@ static counts_t exceedQueryGen(unsigned int rate, int seconds, std::function top_) { - setLuaNoSideEffect(); - uint64_t top = top_ ? *top_ : 10U; - map counts; - unsigned int total=0; - { - for (const auto& shard : g_rings.d_shards) { - auto rl = shard->queryRing.lock(); - for(const auto& c : *rl) { - counts[c.requestor]++; - total++; - } + setLuaNoSideEffect(); + uint64_t top = top_ ? *top_ : 10U; + map counts; + unsigned int total = 0; + { + for (const auto& shard : g_rings.d_shards) { + auto rl = shard->queryRing.lock(); + for (const auto& c : *rl) { + counts[c.requestor]++; + total++; } } - vector> rcounts; - rcounts.reserve(counts.size()); - for(const auto& c : counts) - rcounts.emplace_back(c.second, c.first); - - sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, - const decltype(rcounts)::value_type& b) { - return b.first < a.first; - }); - unsigned int count=1, rest=0; - boost::format fmt("%4d %-40s %4d %4.1f%%\n"); - for(const auto& rc : rcounts) { - if(count==top+1) - rest+=rc.first; - else - g_outputBuffer += (fmt % (count++) % rc.second.toString() % rc.first % (100.0*rc.first/total)).str(); - } - g_outputBuffer += (fmt % (count) % "Rest" % rest % (total > 0 ? 100.0*rest/total : 100.0)).str(); - }); + } + vector> rcounts; + rcounts.reserve(counts.size()); + for (const auto& c : counts) + rcounts.emplace_back(c.second, c.first); + + sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, const decltype(rcounts)::value_type& b) { + return b.first < a.first; + }); + unsigned int count = 1, rest = 0; + boost::format fmt("%4d %-40s %4d %4.1f%%\n"); + for (const auto& rc : rcounts) { + if (count == top + 1) + rest += rc.first; + else + g_outputBuffer += (fmt % (count++) % rc.second.toString() % rc.first % (100.0 * rc.first / total)).str(); + } + g_outputBuffer += (fmt % (count) % "Rest" % rest % (total > 0 ? 100.0 * rest / total : 100.0)).str(); + }); luaCtx.writeFunction("getTopQueries", [](uint64_t top, boost::optional labels) { - setLuaNoSideEffect(); - map counts; - unsigned int total=0; - if(!labels) { - for (const auto& shard : g_rings.d_shards) { - auto rl = shard->queryRing.lock(); - for(const auto& a : *rl) { - counts[a.name]++; - total++; - } + setLuaNoSideEffect(); + map counts; + unsigned int total = 0; + if (!labels) { + for (const auto& shard : g_rings.d_shards) { + auto rl = shard->queryRing.lock(); + for (const auto& a : *rl) { + counts[a.name]++; + total++; } } - else { - unsigned int lab = *labels; - for (const auto& shard : g_rings.d_shards) { - auto rl = shard->queryRing.lock(); - // coverity[auto_causes_copy] - for (auto a : *rl) { - a.name.trimToLabels(lab); - counts[a.name]++; - total++; - } + } + else { + unsigned int lab = *labels; + for (const auto& shard : g_rings.d_shards) { + auto rl = shard->queryRing.lock(); + // coverity[auto_causes_copy] + for (auto a : *rl) { + a.name.trimToLabels(lab); + counts[a.name]++; + total++; } } - // cout<<"Looked at "<> rcounts; - rcounts.reserve(counts.size()); - for(const auto& c : counts) - rcounts.emplace_back(c.second, c.first.makeLowerCase()); - - sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, - const decltype(rcounts)::value_type& b) { - return b.first < a.first; - }); - - std::unordered_map>> ret; - unsigned int count=1, rest=0; - for(const auto& rc : rcounts) { - if(count==top+1) - rest+=rc.first; - else - ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); - } - - if (total > 0) { - ret.insert({count, {"Rest", rest, 100.0*rest/total}}); - } - else { - ret.insert({count, {"Rest", rest, 100.0}}); - } + } + // cout<<"Looked at "<> rcounts; + rcounts.reserve(counts.size()); + for (const auto& c : counts) + rcounts.emplace_back(c.second, c.first.makeLowerCase()); + + sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, const decltype(rcounts)::value_type& b) { + return b.first < a.first; + }); + + std::unordered_map>> ret; + unsigned int count = 1, rest = 0; + for (const auto& rc : rcounts) { + if (count == top + 1) + rest += rc.first; + else + ret.insert({count++, {rc.second.toString(), rc.first, 100.0 * rc.first / total}}); + } - return ret; + if (total > 0) { + ret.insert({count, {"Rest", rest, 100.0 * rest / total}}); + } + else { + ret.insert({count, {"Rest", rest, 100.0}}); + } - }); + return ret; + }); luaCtx.executeCode(R"(function topQueries(top, labels) top = top or 10; for k,v in ipairs(getTopQueries(top,labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2], v[3])) end end)"); luaCtx.writeFunction("getResponseRing", []() { - setLuaNoSideEffect(); - size_t totalEntries = 0; - std::vector> rings; - rings.reserve(g_rings.getNumberOfShards()); - for (const auto& shard : g_rings.d_shards) { - { - auto rl = shard->respRing.lock(); - rings.push_back(*rl); - } - totalEntries += rings.back().size(); - } - vector > > ret; - ret.reserve(totalEntries); - decltype(ret)::value_type item; - for (size_t idx = 0; idx < rings.size(); idx++) { - for(const auto& r : rings[idx]) { - item["name"]=r.name.toString(); - item["qtype"]=r.qtype; - item["rcode"]=r.dh.rcode; - item["usec"]=r.usec; - ret.push_back(item); - } + setLuaNoSideEffect(); + size_t totalEntries = 0; + std::vector> rings; + rings.reserve(g_rings.getNumberOfShards()); + for (const auto& shard : g_rings.d_shards) { + { + auto rl = shard->respRing.lock(); + rings.push_back(*rl); } - return ret; - }); + totalEntries += rings.back().size(); + } + vector>> ret; + ret.reserve(totalEntries); + decltype(ret)::value_type item; + for (size_t idx = 0; idx < rings.size(); idx++) { + for (const auto& r : rings[idx]) { + item["name"] = r.name.toString(); + item["qtype"] = r.qtype; + item["rcode"] = r.dh.rcode; + item["usec"] = r.usec; + ret.push_back(item); + } + } + return ret; + }); luaCtx.writeFunction("getTopResponses", [](uint64_t top, uint64_t kind, boost::optional labels) { - return getGenResponses(top, labels, [kind](const Rings::Response& r) { return r.dh.rcode == kind; }); - }); + return getGenResponses(top, labels, [kind](const Rings::Response& r) { return r.dh.rcode == kind; }); + }); luaCtx.executeCode(R"(function topResponses(top, kind, labels) top = top or 10; kind = kind or 0; for k,v in ipairs(getTopResponses(top, kind, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); - luaCtx.writeFunction("getSlowResponses", [](uint64_t top, uint64_t msec, boost::optional labels) { - return getGenResponses(top, labels, [msec](const Rings::Response& r) { return r.usec > msec*1000; }); - }); - + return getGenResponses(top, labels, [msec](const Rings::Response& r) { return r.usec > msec * 1000; }); + }); luaCtx.executeCode(R"(function topSlow(top, msec, labels) top = top or 10; msec = msec or 500; for k,v in ipairs(getSlowResponses(top, msec, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); luaCtx.writeFunction("getTopBandwidth", [](uint64_t top) { - setLuaNoSideEffect(); - return g_rings.getTopBandwidth(top); - }); + setLuaNoSideEffect(); + return g_rings.getTopBandwidth(top); + }); luaCtx.executeCode(R"(function topBandwidth(top) top = top or 10; for k,v in ipairs(getTopBandwidth(top)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); #endif /* DISABLE_TOP_N_BINDINGS */ luaCtx.writeFunction("delta", []() { - setLuaNoSideEffect(); - // we hold the lua lock already! - for(const auto& d : g_confDelta) { - struct tm tm; - localtime_r(&d.first.tv_sec, &tm); - char date[80]; - strftime(date, sizeof(date)-1, "-- %a %b %d %Y %H:%M:%S %Z\n", &tm); - g_outputBuffer += date; - g_outputBuffer += d.second + "\n"; - } - }); + setLuaNoSideEffect(); + // we hold the lua lock already! + for (const auto& d : g_confDelta) { + struct tm tm; + localtime_r(&d.first.tv_sec, &tm); + char date[80]; + strftime(date, sizeof(date) - 1, "-- %a %b %d %Y %H:%M:%S %Z\n", &tm); + g_outputBuffer += date; + g_outputBuffer += d.second + "\n"; + } + }); luaCtx.writeFunction("grepq", [](LuaTypeOrArrayOf inp, boost::optional limit, boost::optional> options) { - setLuaNoSideEffect(); - boost::optional nm; - boost::optional dn; - int msec = -1; - std::unique_ptr outputFile{nullptr, fclose}; - - if (options) { - std::string outputFileName; - if (getOptionalValue(options, "outputFile", outputFileName) > 0) { - int fd = open(outputFileName.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0600); - if (fd < 0) { - g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; - return; - } - outputFile = std::unique_ptr(fdopen(fd, "w"), fclose); - if (outputFile == nullptr) { - g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; - close(fd); - return; - } - } - checkAllParametersConsumed("grepq", options); - } + setLuaNoSideEffect(); + boost::optional nm; + boost::optional dn; + int msec = -1; + std::unique_ptr outputFile{nullptr, fclose}; + + if (options) { + std::string outputFileName; + if (getOptionalValue(options, "outputFile", outputFileName) > 0) { + int fd = open(outputFileName.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0600); + if (fd < 0) { + g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; + return; + } + outputFile = std::unique_ptr(fdopen(fd, "w"), fclose); + if (outputFile == nullptr) { + g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n"; + close(fd); + return; + } + } + checkAllParametersConsumed("grepq", options); + } - vector vec; - auto str = boost::get(&inp); - if (str) { - vec.push_back(*str); - } - else { - auto v = boost::get>(inp); - for (const auto& a: v) { - vec.push_back(a.second); - } + vector vec; + auto str = boost::get(&inp); + if (str) { + vec.push_back(*str); + } + else { + auto v = boost::get>(inp); + for (const auto& a : v) { + vec.push_back(a.second); } + } - for (const auto& s : vec) { - try { - nm = Netmask(s); + for (const auto& s : vec) { + try { + nm = Netmask(s); + } + catch (...) { + if (boost::ends_with(s, "ms") && sscanf(s.c_str(), "%ums", &msec)) { + ; } - catch (...) { - if (boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) { - ; + else { + try { + dn = DNSName(s); } - else { - try { - dn = DNSName(s); - } - catch (...) { - g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask"; - return; - } + catch (...) { + g_outputBuffer = "Could not parse '" + s + "' as domain name or netmask"; + return; } } } + } - std::vector qr; - std::vector rr; - qr.reserve(g_rings.getNumberOfQueryEntries()); - rr.reserve(g_rings.getNumberOfResponseEntries()); - for (const auto& shard : g_rings.d_shards) { - { - auto rl = shard->queryRing.lock(); - for (const auto& entry : *rl) { - qr.push_back(entry); - } + std::vector qr; + std::vector rr; + qr.reserve(g_rings.getNumberOfQueryEntries()); + rr.reserve(g_rings.getNumberOfResponseEntries()); + for (const auto& shard : g_rings.d_shards) { + { + auto rl = shard->queryRing.lock(); + for (const auto& entry : *rl) { + qr.push_back(entry); } - { - auto rl = shard->respRing.lock(); - for (const auto& entry : *rl) { - rr.push_back(entry); - } + } + { + auto rl = shard->respRing.lock(); + for (const auto& entry : *rl) { + rr.push_back(entry); } } + } - sort(qr.begin(), qr.end(), [](const decltype(qr)::value_type& a, const decltype(qr)::value_type& b) { - return b.when < a.when; - }); - - sort(rr.begin(), rr.end(), [](const decltype(rr)::value_type& a, const decltype(rr)::value_type& b) { - return b.when < a.when; - }); + sort(qr.begin(), qr.end(), [](const decltype(qr)::value_type& a, const decltype(qr)::value_type& b) { + return b.when < a.when; + }); - unsigned int num=0; - struct timespec now; - gettime(&now); + sort(rr.begin(), rr.end(), [](const decltype(rr)::value_type& a, const decltype(rr)::value_type& b) { + return b.when < a.when; + }); - std::multimap out; + unsigned int num = 0; + struct timespec now; + gettime(&now); - boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n"); - const auto headLine = (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); - if (!outputFile) { - g_outputBuffer += headLine; - } - else { - fprintf(outputFile.get(), "%s", headLine.c_str()); - } + std::multimap out; - if (msec == -1) { - for (const auto& c : qr) { - bool nmmatch = true; - bool dnmatch = true; - if (nm) { - nmmatch = nm->match(c.requestor); - } - if (dn) { - if (c.name.empty()) { - dnmatch = false; - } - else { - dnmatch = c.name.isPartOf(*dn); - } - } - if (nmmatch && dnmatch) { - QType qt(c.qtype); - std::string extra; - if (c.dh.opcode != 0) { - extra = " (" + Opcode::to_s(c.dh.opcode) + ")"; - } - out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % dnsdist::Protocol(c.protocol).toString() % "" % htons(c.dh.id) % c.name.toString() % qt.toString() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % ("Question" + extra)).str()); - - if (limit && *limit == ++num) { - break; - } - } - } - } - num = 0; + boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n"); + const auto headLine = (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); + if (!outputFile) { + g_outputBuffer += headLine; + } + else { + fprintf(outputFile.get(), "%s", headLine.c_str()); + } - string extra; - for (const auto& c : rr) { + if (msec == -1) { + for (const auto& c : qr) { bool nmmatch = true; bool dnmatch = true; - bool msecmatch = true; if (nm) { nmmatch = nm->match(c.requestor); } @@ -552,169 +510,201 @@ void setupLuaInspection(LuaContext& luaCtx) dnmatch = c.name.isPartOf(*dn); } } - if (msec != -1) { - msecmatch = (c.usec/1000 > (unsigned int)msec); - } - - if (nmmatch && dnmatch && msecmatch) { + if (nmmatch && dnmatch) { QType qt(c.qtype); - if (!c.dh.rcode) { - extra = ". " +std::to_string(htons(c.dh.ancount)) + " answers"; - } - else { - extra.clear(); - } - - std::string server = c.ds.toStringWithPort(); - std::string protocol = dnsdist::Protocol(c.protocol).toString(); - if (server == "0.0.0.0:0") { - server = "Cache"; - protocol = "-"; - } - if (c.usec != std::numeric_limits::max()) { - out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % protocol % server % htons(c.dh.id) % c.name.toString() % qt.toString() % (c.usec / 1000.0) % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str()); - } - else { - out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % protocol % server % htons(c.dh.id) % c.name.toString() % qt.toString() % "T.O" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str()); + std::string extra; + if (c.dh.opcode != 0) { + extra = " (" + Opcode::to_s(c.dh.opcode) + ")"; } + out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % dnsdist::Protocol(c.protocol).toString() % "" % htons(c.dh.id) % c.name.toString() % qt.toString() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % ("Question" + extra)).str()); if (limit && *limit == ++num) { break; } } } + } + num = 0; - for (const auto& p : out) { - if (!outputFile) { - g_outputBuffer += p.second; + string extra; + for (const auto& c : rr) { + bool nmmatch = true; + bool dnmatch = true; + bool msecmatch = true; + if (nm) { + nmmatch = nm->match(c.requestor); + } + if (dn) { + if (c.name.empty()) { + dnmatch = false; } else { - fprintf(outputFile.get(), "%s", p.second.c_str()); + dnmatch = c.name.isPartOf(*dn); } } - }); - - luaCtx.writeFunction("showResponseLatency", []() { - setLuaNoSideEffect(); - map histo; - double bin=100; - for(int i=0; i < 15; ++i) { - histo[bin]; - bin*=2; + if (msec != -1) { + msecmatch = (c.usec / 1000 > (unsigned int)msec); } - double totlat=0; - unsigned int size=0; - { - for (const auto& shard : g_rings.d_shards) { - auto rl = shard->respRing.lock(); - for(const auto& r : *rl) { - /* skip actively discovered timeouts */ - if (r.usec == std::numeric_limits::max()) - continue; - - ++size; - auto iter = histo.lower_bound(r.usec); - if(iter != histo.end()) - iter->second++; - else - histo.rbegin()++; - totlat+=r.usec; - } + if (nmmatch && dnmatch && msecmatch) { + QType qt(c.qtype); + if (!c.dh.rcode) { + extra = ". " + std::to_string(htons(c.dh.ancount)) + " answers"; + } + else { + extra.clear(); + } + + std::string server = c.ds.toStringWithPort(); + std::string protocol = dnsdist::Protocol(c.protocol).toString(); + if (server == "0.0.0.0:0") { + server = "Cache"; + protocol = "-"; + } + if (c.usec != std::numeric_limits::max()) { + out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % protocol % server % htons(c.dh.id) % c.name.toString() % qt.toString() % (c.usec / 1000.0) % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str()); + } + else { + out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % protocol % server % htons(c.dh.id) % c.name.toString() % qt.toString() % "T.O" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str()); + } + + if (limit && *limit == ++num) { + break; } } + } - if (size == 0) { - g_outputBuffer = "No traffic yet.\n"; - return; + for (const auto& p : out) { + if (!outputFile) { + g_outputBuffer += p.second; + } + else { + fprintf(outputFile.get(), "%s", p.second.c_str()); } + } + }); - g_outputBuffer = (boost::format("Average response latency: %.02f ms\n") % (0.001*totlat/size)).str(); - double highest=0; + luaCtx.writeFunction("showResponseLatency", []() { + setLuaNoSideEffect(); + map histo; + double bin = 100; + for (int i = 0; i < 15; ++i) { + histo[bin]; + bin *= 2; + } - for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { - highest=std::max(highest, iter->second*1.0); - } - boost::format fmt("%7.2f\t%s\n"); - g_outputBuffer += (fmt % "ms" % "").str(); + double totlat = 0; + unsigned int size = 0; + { + for (const auto& shard : g_rings.d_shards) { + auto rl = shard->respRing.lock(); + for (const auto& r : *rl) { + /* skip actively discovered timeouts */ + if (r.usec == std::numeric_limits::max()) + continue; - for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { - int stars = (70.0 * iter->second/highest); - char c='*'; - if(!stars && iter->second) { - stars=1; // you get 1 . to show something is there.. - if(70.0*iter->second/highest > 0.5) - c=':'; - else - c='.'; - } - g_outputBuffer += (fmt % (iter->first/1000.0) % string(stars, c)).str(); + ++size; + auto iter = histo.lower_bound(r.usec); + if (iter != histo.end()) + iter->second++; + else + histo.rbegin()++; + totlat += r.usec; + } } - }); + } - luaCtx.writeFunction("showTCPStats", [] { - setLuaNoSideEffect(); - 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 << endl; + if (size == 0) { + g_outputBuffer = "No traffic yet.\n"; + return; + } - ret << "Frontends:" << endl; - fmt = boost::format("%-3d %-20.20s %-20d %-20d %-20d %-25d %-20d %-20d %-20d %-20f %-20f %-20d %-20d %-25d %-25d %-15d %-15d %-15d %-15d %-15d"); - ret << (fmt % "#" % "Address" % "Connections" % "Max concurrent conn" % "Died reading query" % "Died sending response" % "Gave up" % "Client timeouts" % "Downstream timeouts" % "Avg queries/conn" % "Avg duration" % "TLS new sessions" % "TLS Resumptions" % "TLS unknown ticket keys" % "TLS inactive ticket keys" % "TLS 1.0" % "TLS 1.1" % "TLS 1.2" % "TLS 1.3" % "TLS other") << endl; + g_outputBuffer = (boost::format("Average response latency: %.02f ms\n") % (0.001 * totlat / size)).str(); + double highest = 0; - size_t counter = 0; - for(const auto& f : g_frontends) { - ret << (fmt % counter % f->local.toStringWithPort() % f->tcpCurrentConnections % f->tcpMaxConcurrentConnections % f->tcpDiedReadingQuery % f->tcpDiedSendingResponse % f->tcpGaveUp % f->tcpClientTimeouts % f->tcpDownstreamTimeouts % f->tcpAvgQueriesPerConnection % f->tcpAvgConnectionDuration % f->tlsNewSessions % f->tlsResumptions % f->tlsUnknownTicketKey % f->tlsInactiveTicketKey % f->tls10queries % f->tls11queries % f->tls12queries % f->tls13queries % f->tlsUnknownqueries) << endl; - ++counter; - } - ret << endl; + for (auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { + highest = std::max(highest, iter->second * 1.0); + } + boost::format fmt("%7.2f\t%s\n"); + g_outputBuffer += (fmt % "ms" % "").str(); + + for (auto iter = histo.cbegin(); iter != histo.cend(); ++iter) { + int stars = (70.0 * iter->second / highest); + char c = '*'; + if (!stars && iter->second) { + stars = 1; // you get 1 . to show something is there.. + if (70.0 * iter->second / highest > 0.5) + c = ':'; + else + c = '.'; + } + g_outputBuffer += (fmt % (iter->first / 1000.0) % string(stars, c)).str(); + } + }); - ret << "Backends:" << endl; - fmt = boost::format("%-3d %-20.20s %-20.20s %-20d %-20d %-25d %-25d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20f %-20f"); - ret << (fmt % "#" % "Name" % "Address" % "Connections" % "Max concurrent conn" % "Died sending query" % "Died reading response" % "Gave up" % "Read timeouts" % "Write timeouts" % "Connect timeouts" % "Too many conn" % "Total connections" % "Reused connections" % "TLS resumptions" % "Avg queries/conn" % "Avg duration") << endl; + luaCtx.writeFunction("showTCPStats", [] { + setLuaNoSideEffect(); + 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 << endl; + + ret << "Frontends:" << endl; + fmt = boost::format("%-3d %-20.20s %-20d %-20d %-20d %-25d %-20d %-20d %-20d %-20f %-20f %-20d %-20d %-25d %-25d %-15d %-15d %-15d %-15d %-15d"); + ret << (fmt % "#" % "Address" % "Connections" % "Max concurrent conn" % "Died reading query" % "Died sending response" % "Gave up" % "Client timeouts" % "Downstream timeouts" % "Avg queries/conn" % "Avg duration" % "TLS new sessions" % "TLS Resumptions" % "TLS unknown ticket keys" % "TLS inactive ticket keys" % "TLS 1.0" % "TLS 1.1" % "TLS 1.2" % "TLS 1.3" % "TLS other") << endl; + + size_t counter = 0; + for (const auto& f : g_frontends) { + ret << (fmt % counter % f->local.toStringWithPort() % f->tcpCurrentConnections % f->tcpMaxConcurrentConnections % f->tcpDiedReadingQuery % f->tcpDiedSendingResponse % f->tcpGaveUp % f->tcpClientTimeouts % f->tcpDownstreamTimeouts % f->tcpAvgQueriesPerConnection % f->tcpAvgConnectionDuration % f->tlsNewSessions % f->tlsResumptions % f->tlsUnknownTicketKey % f->tlsInactiveTicketKey % f->tls10queries % f->tls11queries % f->tls12queries % f->tls13queries % f->tlsUnknownqueries) << endl; + ++counter; + } + ret << endl; - auto states = g_dstates.getLocal(); - counter = 0; - for(const auto& s : *states) { - ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % s->tcpCurrentConnections % s->tcpMaxConcurrentConnections % s->tcpDiedSendingQuery % s->tcpDiedReadingResponse % s->tcpGaveUp % s->tcpReadTimeouts % s->tcpWriteTimeouts % s->tcpConnectTimeouts % s->tcpTooManyConcurrentConnections % s->tcpNewConnections % s->tcpReusedConnections % s->tlsResumptions % s->tcpAvgQueriesPerConnection % s->tcpAvgConnectionDuration) << endl; - ++counter; - } + ret << "Backends:" << endl; + fmt = boost::format("%-3d %-20.20s %-20.20s %-20d %-20d %-25d %-25d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20f %-20f"); + ret << (fmt % "#" % "Name" % "Address" % "Connections" % "Max concurrent conn" % "Died sending query" % "Died reading response" % "Gave up" % "Read timeouts" % "Write timeouts" % "Connect timeouts" % "Too many conn" % "Total connections" % "Reused connections" % "TLS resumptions" % "Avg queries/conn" % "Avg duration") << endl; - g_outputBuffer=ret.str(); - }); + auto states = g_dstates.getLocal(); + counter = 0; + for (const auto& s : *states) { + ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % s->tcpCurrentConnections % s->tcpMaxConcurrentConnections % s->tcpDiedSendingQuery % s->tcpDiedReadingResponse % s->tcpGaveUp % s->tcpReadTimeouts % s->tcpWriteTimeouts % s->tcpConnectTimeouts % s->tcpTooManyConcurrentConnections % s->tcpNewConnections % s->tcpReusedConnections % s->tlsResumptions % s->tcpAvgQueriesPerConnection % s->tcpAvgConnectionDuration) << endl; + ++counter; + } + + g_outputBuffer = ret.str(); + }); luaCtx.writeFunction("showTLSErrorCounters", [] { - setLuaNoSideEffect(); - ostringstream ret; - boost::format fmt("%-3d %-20.20s %-23d %-23d %-23d %-23d %-23d %-23d %-23d %-23d"); + setLuaNoSideEffect(); + ostringstream ret; + boost::format fmt("%-3d %-20.20s %-23d %-23d %-23d %-23d %-23d %-23d %-23d %-23d"); - ret << (fmt % "#" % "Address" % "DH key too small" % "Inappropriate fallback" % "No shared cipher" % "Unknown cipher type" % "Unknown exchange type" % "Unknown protocol" % "Unsupported EC" % "Unsupported protocol") << endl; + ret << (fmt % "#" % "Address" % "DH key too small" % "Inappropriate fallback" % "No shared cipher" % "Unknown cipher type" % "Unknown exchange type" % "Unknown protocol" % "Unsupported EC" % "Unsupported protocol") << endl; - size_t counter = 0; - for(const auto& f : g_frontends) { - if (!f->hasTLS()) { - continue; - } - const TLSErrorCounters* errorCounters = nullptr; - if (f->tlsFrontend != nullptr) { - errorCounters = &f->tlsFrontend->d_tlsCounters; - } - else if (f->dohFrontend != nullptr) { - errorCounters = &f->dohFrontend->d_tlsContext.d_tlsCounters; - } - if (errorCounters == nullptr) { - continue; - } - - ret << (fmt % counter % f->local.toStringWithPort() % errorCounters->d_dhKeyTooSmall % errorCounters->d_inappropriateFallBack % errorCounters->d_noSharedCipher % errorCounters->d_unknownCipherType % errorCounters->d_unknownKeyExchangeType % errorCounters->d_unknownProtocol % errorCounters->d_unsupportedEC % errorCounters->d_unsupportedProtocol) << endl; - ++counter; + size_t counter = 0; + for (const auto& f : g_frontends) { + if (!f->hasTLS()) { + continue; + } + const TLSErrorCounters* errorCounters = nullptr; + if (f->tlsFrontend != nullptr) { + errorCounters = &f->tlsFrontend->d_tlsCounters; + } + else if (f->dohFrontend != nullptr) { + errorCounters = &f->dohFrontend->d_tlsContext.d_tlsCounters; + } + if (errorCounters == nullptr) { + continue; } - ret << endl; - g_outputBuffer=ret.str(); - }); + ret << (fmt % counter % f->local.toStringWithPort() % errorCounters->d_dhKeyTooSmall % errorCounters->d_inappropriateFallBack % errorCounters->d_noSharedCipher % errorCounters->d_unknownCipherType % errorCounters->d_unknownKeyExchangeType % errorCounters->d_unknownProtocol % errorCounters->d_unsupportedEC % errorCounters->d_unsupportedProtocol) << endl; + ++counter; + } + ret << endl; + + g_outputBuffer = ret.str(); + }); luaCtx.writeFunction("requestTCPStatesDump", [] { setLuaNoSideEffect(); @@ -730,95 +720,95 @@ void setupLuaInspection(LuaContext& luaCtx) }); luaCtx.writeFunction("dumpStats", [] { - setLuaNoSideEffect(); - vector leftcolumn, rightcolumn; - - boost::format fmt("%-35s\t%+11s"); - g_outputBuffer.clear(); - auto entries = *dnsdist::metrics::g_stats.entries.read_lock(); - sort(entries.begin(), entries.end(), - [](const decltype(entries)::value_type& a, const decltype(entries)::value_type& b) { - return a.d_name < b.d_name; - }); - boost::format flt(" %9.1f"); - for (const auto& entry : entries) { - string second; - if (const auto& val = std::get_if(&entry.d_value)) { - second = std::to_string((*val)->load()); - } - else if (const auto& adval = std::get_if*>(&entry.d_value)) { - second = (flt % (*adval)->load()).str(); - } - else if (const auto& dval = std::get_if(&entry.d_value)) { - second = (flt % (**dval)).str(); - } - else if (const auto& func = std::get_if(&entry.d_value)) { - second = std::to_string((*func)(entry.d_name)); - } + setLuaNoSideEffect(); + vector leftcolumn, rightcolumn; - if (leftcolumn.size() < entries.size() / 2) { - leftcolumn.push_back((fmt % entry.d_name % second).str()); - } - else { - rightcolumn.push_back((fmt % entry.d_name % second).str()); - } + boost::format fmt("%-35s\t%+11s"); + g_outputBuffer.clear(); + auto entries = *dnsdist::metrics::g_stats.entries.read_lock(); + sort(entries.begin(), entries.end(), + [](const decltype(entries)::value_type& a, const decltype(entries)::value_type& b) { + return a.d_name < b.d_name; + }); + boost::format flt(" %9.1f"); + for (const auto& entry : entries) { + string second; + if (const auto& val = std::get_if(&entry.d_value)) { + second = std::to_string((*val)->load()); + } + else if (const auto& adval = std::get_if*>(&entry.d_value)) { + second = (flt % (*adval)->load()).str(); + } + else if (const auto& dval = std::get_if(&entry.d_value)) { + second = (flt % (**dval)).str(); + } + else if (const auto& func = std::get_if(&entry.d_value)) { + second = std::to_string((*func)(entry.d_name)); + } + + if (leftcolumn.size() < entries.size() / 2) { + leftcolumn.push_back((fmt % entry.d_name % second).str()); + } + else { + rightcolumn.push_back((fmt % entry.d_name % second).str()); } + } - auto leftiter=leftcolumn.begin(), rightiter=rightcolumn.begin(); - boost::format clmn("%|0t|%1% %|51t|%2%\n"); + auto leftiter = leftcolumn.begin(), rightiter = rightcolumn.begin(); + boost::format clmn("%|0t|%1% %|51t|%2%\n"); - for(;leftiter != leftcolumn.end() || rightiter != rightcolumn.end();) { - string lentry, rentry; - if(leftiter!= leftcolumn.end()) { - lentry = *leftiter; - leftiter++; - } - if(rightiter!= rightcolumn.end()) { - rentry = *rightiter; - rightiter++; - } - g_outputBuffer += (clmn % lentry % rentry).str(); + for (; leftiter != leftcolumn.end() || rightiter != rightcolumn.end();) { + string lentry, rentry; + if (leftiter != leftcolumn.end()) { + lentry = *leftiter; + leftiter++; } - }); + if (rightiter != rightcolumn.end()) { + rentry = *rightiter; + rightiter++; + } + g_outputBuffer += (clmn % lentry % rentry).str(); + } + }); #ifndef DISABLE_DYNBLOCKS #ifndef DISABLE_DEPRECATED_DYNBLOCK luaCtx.writeFunction("exceedServFails", [](unsigned int rate, int seconds) { - setLuaNoSideEffect(); - return exceedRCode(rate, seconds, RCode::ServFail); - }); + setLuaNoSideEffect(); + return exceedRCode(rate, seconds, RCode::ServFail); + }); luaCtx.writeFunction("exceedNXDOMAINs", [](unsigned int rate, int seconds) { - setLuaNoSideEffect(); - return exceedRCode(rate, seconds, RCode::NXDomain); - }); + setLuaNoSideEffect(); + return exceedRCode(rate, seconds, RCode::NXDomain); + }); luaCtx.writeFunction("exceedRespByterate", [](unsigned int rate, int seconds) { - setLuaNoSideEffect(); - return exceedRespByterate(rate, seconds); - }); + setLuaNoSideEffect(); + return exceedRespByterate(rate, seconds); + }); luaCtx.writeFunction("exceedQTypeRate", [](uint16_t type, unsigned int rate, int seconds) { - setLuaNoSideEffect(); - return exceedQueryGen(rate, seconds, [type](counts_t& counts, const Rings::Query& q) { - if(q.qtype==type) - counts[q.requestor]++; - }); + setLuaNoSideEffect(); + return exceedQueryGen(rate, seconds, [type](counts_t& counts, const Rings::Query& q) { + if (q.qtype == type) + counts[q.requestor]++; }); + }); luaCtx.writeFunction("exceedQRate", [](unsigned int rate, int seconds) { - setLuaNoSideEffect(); - return exceedQueryGen(rate, seconds, [](counts_t& counts, const Rings::Query& q) { - counts[q.requestor]++; - }); + setLuaNoSideEffect(); + return exceedQueryGen(rate, seconds, [](counts_t& counts, const Rings::Query& q) { + counts[q.requestor]++; }); + }); luaCtx.writeFunction("getRespRing", getRespRing); /* StatNode */ - luaCtx.registerFunction("numChildren", - [](const StatNode& sn) -> unsigned int { - return sn.children.size(); - } ); + luaCtx.registerFunction("numChildren", + [](const StatNode& sn) -> unsigned int { + return sn.children.size(); + }); luaCtx.registerMember("fullname", &StatNode::fullname); luaCtx.registerMember("labelsCount", &StatNode::labelsCount); luaCtx.registerMember("servfails", &StatNode::Stat::servfails); @@ -830,124 +820,124 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.registerMember("hits", &StatNode::Stat::hits); luaCtx.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional seconds) { - statNodeRespRing(std::move(visitor), seconds ? *seconds : 0U); - }); + statNodeRespRing(std::move(visitor), seconds ? *seconds : 0U); + }); #endif /* DISABLE_DEPRECATED_DYNBLOCK */ /* DynBlockRulesGroup */ luaCtx.writeFunction("dynBlockRulesGroup", []() { return std::make_shared(); }); - luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQueryRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { - if (group) { - group->setQueryRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); - } - }); - luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setResponseByteRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { - if (group) { - group->setResponseByteRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); - } - }); - luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, DynBlockRulesGroup::smtVisitor_t)>("setSuffixMatchRule", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, DynBlockRulesGroup::smtVisitor_t visitor) { - if (group) { - group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); - } - }); - luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, dnsdist_ffi_stat_node_visitor_t visitor) { - if (group) { - group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); - } - }); - luaCtx.registerFunction::*)(const dnsdist_ffi_dynamic_block_inserted_hook&)>("setNewBlockInsertedHook", [](std::shared_ptr& group, const dnsdist_ffi_dynamic_block_inserted_hook& hook) { - if (group) { - group->setNewBlockHook(hook); - } - }); - luaCtx.registerFunction::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setRCodeRate", [](std::shared_ptr& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { - if (group) { - group->setRCodeRate(rcode, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); - } - }); - luaCtx.registerFunction::*)(uint8_t, double, unsigned int, const std::string&, unsigned int, size_t, boost::optional, boost::optional)>("setRCodeRatio", [](std::shared_ptr& group, uint8_t rcode, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, boost::optional action, boost::optional warningRatio) { - if (group) { - group->setRCodeRatio(rcode, ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses); - } - }); - luaCtx.registerFunction::*)(uint16_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQTypeRate", [](std::shared_ptr& group, uint16_t qtype, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { - if (group) { - group->setQTypeRate(qtype, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); - } - }); - luaCtx.registerFunction::*)(double, unsigned int, const std::string&, unsigned int, size_t, double, boost::optional, boost::optional)>("setCacheMissRatio", [](std::shared_ptr& group, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, double minimumGlobalCacheHitRatio, boost::optional action, boost::optional warningRatio) { - if (group) { - group->setCacheMissRatio(ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses, minimumGlobalCacheHitRatio); - } - }); - luaCtx.registerFunction::*)(uint8_t, uint8_t, uint8_t)>("setMasks", [](std::shared_ptr& group, uint8_t v4, uint8_t v6, uint8_t port) { - if (group) { - if (v4 > 32) { - throw std::runtime_error("Trying to set an invalid IPv4 mask (" + std::to_string(v4) + ") to a Dynamic Block object"); - } - if (v6 > 128) { - throw std::runtime_error("Trying to set an invalid IPv6 mask (" + std::to_string(v6) + ") to a Dynamic Block object"); - } - if (port > 16) { - throw std::runtime_error("Trying to set an invalid port mask (" + std::to_string(port) + ") to a Dynamic Block object"); - } - if (port > 0 && v4 != 32) { - throw std::runtime_error("Setting a non-zero port mask for Dynamic Blocks while only considering parts of IPv4 addresses does not make sense"); - } - group->setMasks(v4, v6, port); - } - }); - luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("excludeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { - if (ranges.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&ranges)) { - group->excludeRange(Netmask(range.second)); - } - } - else if (ranges.type() == typeid(NetmaskGroup)) { - group->excludeRange(*boost::get(&ranges)); - } - else { - group->excludeRange(Netmask(*boost::get(&ranges))); - } - }); - luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("includeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { - if (ranges.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&ranges)) { - group->includeRange(Netmask(range.second)); - } + luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQueryRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + if (group) { + group->setQueryRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); + } + }); + luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setResponseByteRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + if (group) { + group->setResponseByteRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); + } + }); + luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, DynBlockRulesGroup::smtVisitor_t)>("setSuffixMatchRule", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, DynBlockRulesGroup::smtVisitor_t visitor) { + if (group) { + group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); + } + }); + luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, dnsdist_ffi_stat_node_visitor_t visitor) { + if (group) { + group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, std::move(visitor)); + } + }); + luaCtx.registerFunction::*)(const dnsdist_ffi_dynamic_block_inserted_hook&)>("setNewBlockInsertedHook", [](std::shared_ptr& group, const dnsdist_ffi_dynamic_block_inserted_hook& hook) { + if (group) { + group->setNewBlockHook(hook); + } + }); + luaCtx.registerFunction::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setRCodeRate", [](std::shared_ptr& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + if (group) { + group->setRCodeRate(rcode, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); + } + }); + luaCtx.registerFunction::*)(uint8_t, double, unsigned int, const std::string&, unsigned int, size_t, boost::optional, boost::optional)>("setRCodeRatio", [](std::shared_ptr& group, uint8_t rcode, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, boost::optional action, boost::optional warningRatio) { + if (group) { + group->setRCodeRatio(rcode, ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses); + } + }); + luaCtx.registerFunction::*)(uint16_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQTypeRate", [](std::shared_ptr& group, uint16_t qtype, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + if (group) { + group->setQTypeRate(qtype, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); + } + }); + luaCtx.registerFunction::*)(double, unsigned int, const std::string&, unsigned int, size_t, double, boost::optional, boost::optional)>("setCacheMissRatio", [](std::shared_ptr& group, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, double minimumGlobalCacheHitRatio, boost::optional action, boost::optional warningRatio) { + if (group) { + group->setCacheMissRatio(ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses, minimumGlobalCacheHitRatio); + } + }); + luaCtx.registerFunction::*)(uint8_t, uint8_t, uint8_t)>("setMasks", [](std::shared_ptr& group, uint8_t v4, uint8_t v6, uint8_t port) { + if (group) { + if (v4 > 32) { + throw std::runtime_error("Trying to set an invalid IPv4 mask (" + std::to_string(v4) + ") to a Dynamic Block object"); } - else if (ranges.type() == typeid(NetmaskGroup)) { - group->includeRange(*boost::get(&ranges)); + if (v6 > 128) { + throw std::runtime_error("Trying to set an invalid IPv6 mask (" + std::to_string(v6) + ") to a Dynamic Block object"); } - else { - group->includeRange(Netmask(*boost::get(&ranges))); + if (port > 16) { + throw std::runtime_error("Trying to set an invalid port mask (" + std::to_string(port) + ") to a Dynamic Block object"); } - }); - luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("removeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { - if (ranges.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&ranges)) { - group->removeRange(Netmask(range.second)); - } + if (port > 0 && v4 != 32) { + throw std::runtime_error("Setting a non-zero port mask for Dynamic Blocks while only considering parts of IPv4 addresses does not make sense"); } - else if (ranges.type() == typeid(NetmaskGroup)) { - group->removeRange(*boost::get(&ranges)); + group->setMasks(v4, v6, port); + } + }); + luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("excludeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { + if (ranges.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&ranges)) { + group->excludeRange(Netmask(range.second)); } - else { - group->removeRange(Netmask(*boost::get(&ranges))); + } + else if (ranges.type() == typeid(NetmaskGroup)) { + group->excludeRange(*boost::get(&ranges)); + } + else { + group->excludeRange(Netmask(*boost::get(&ranges))); + } + }); + luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("includeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { + if (ranges.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&ranges)) { + group->includeRange(Netmask(range.second)); } - }); - luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("excludeDomains", [](std::shared_ptr& group, LuaTypeOrArrayOf domains) { - if (domains.type() == typeid(LuaArray)) { - for (const auto& range : *boost::get>(&domains)) { - group->excludeDomain(DNSName(range.second)); - } + } + else if (ranges.type() == typeid(NetmaskGroup)) { + group->includeRange(*boost::get(&ranges)); + } + else { + group->includeRange(Netmask(*boost::get(&ranges))); + } + }); + luaCtx.registerFunction::*)(boost::variant, NetmaskGroup>)>("removeRange", [](std::shared_ptr& group, boost::variant, NetmaskGroup> ranges) { + if (ranges.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&ranges)) { + group->removeRange(Netmask(range.second)); } - else { - group->excludeDomain(DNSName(*boost::get(&domains))); + } + else if (ranges.type() == typeid(NetmaskGroup)) { + group->removeRange(*boost::get(&ranges)); + } + else { + group->removeRange(Netmask(*boost::get(&ranges))); + } + }); + luaCtx.registerFunction::*)(LuaTypeOrArrayOf)>("excludeDomains", [](std::shared_ptr& group, LuaTypeOrArrayOf domains) { + if (domains.type() == typeid(LuaArray)) { + for (const auto& range : *boost::get>(&domains)) { + group->excludeDomain(DNSName(range.second)); } - }); - luaCtx.registerFunction::*)()>("apply", [](std::shared_ptr& group) { + } + else { + group->excludeDomain(DNSName(*boost::get(&domains))); + } + }); + luaCtx.registerFunction::*)()>("apply", [](std::shared_ptr& group) { group->apply(); }); luaCtx.registerFunction("setQuiet", &DynBlockRulesGroup::setQuiet); @@ -957,7 +947,8 @@ void setupLuaInspection(LuaContext& luaCtx) luaCtx.registerMember("reason", &DynBlock::reason); luaCtx.registerMember("domain", &DynBlock::domain); luaCtx.registerMember("until", &DynBlock::until); - luaCtx.registerMember("blocks", [](const DynBlock& block) { return block.blocks.load(); }, [](DynBlock& block, [[maybe_unused]] unsigned int blocks) { }); + luaCtx.registerMember( + "blocks", [](const DynBlock& block) { return block.blocks.load(); }, [](DynBlock& block, [[maybe_unused]] unsigned int blocks) {}); luaCtx.registerMember("action", &DynBlock::action); luaCtx.registerMember("warning", &DynBlock::warning); luaCtx.registerMember("bpf", &DynBlock::bpf); diff --git a/pdns/dnsdistdist/dnsdist-lua-rules.cc b/pdns/dnsdistdist/dnsdist-lua-rules.cc index f53b98be39..d58bedba76 100644 --- a/pdns/dnsdistdist/dnsdist-lua-rules.cc +++ b/pdns/dnsdistdist/dnsdist-lua-rules.cc @@ -36,7 +36,8 @@ std::shared_ptr makeRule(const luadnsrule_t& var, const std::string& ca auto add = [&nmg, &smn, &suffixSeen](const string& src) { try { nmg.addMask(src); // need to try mask first, all masks are domain names! - } catch (...) { + } + catch (...) { suffixSeen = true; smn.add(DNSName(src)); } @@ -91,9 +92,9 @@ void parseRuleParams(boost::optional& params, boost::uuids::uui creationOrder = s_creationOrder++; } -typedef LuaAssociativeTable > > ruleparams_t; +typedef LuaAssociativeTable>> ruleparams_t; -template +template static std::string rulesToString(const std::vector& rules, boost::optional& vars) { int num = 0; @@ -108,7 +109,7 @@ static std::string rulesToString(const std::vector& rules, boost::optionaltoString().substr(0, truncateRuleWidth); result += (fmt % num % lim.d_name % boost::uuids::to_string(lim.d_id) % lim.d_creationOrder % lim.d_rule->d_matches % desc % lim.d_action->toString()).str(); ++num; @@ -117,25 +118,27 @@ static std::string rulesToString(const std::vector& rules, boost::optionaltoString().substr(0, truncateRuleWidth); - result += (fmt % num % lim.d_name % lim.d_rule->d_matches % desc % lim.d_action->toString()).str(); + result += (fmt % num % lim.d_name % lim.d_rule->d_matches % desc % lim.d_action->toString()).str(); ++num; } } return result; } -template -static void showRules(GlobalStateHolder > *someRuleActions, boost::optional& vars) { +template +static void showRules(GlobalStateHolder>* someRuleActions, boost::optional& vars) +{ setLuaNoSideEffect(); auto rules = someRuleActions->getLocal(); g_outputBuffer += rulesToString(*rules, vars); } -template -static void rmRule(GlobalStateHolder > *someRuleActions, const boost::variant& id) { +template +static void rmRule(GlobalStateHolder>* someRuleActions, const boost::variant& id) +{ setLuaSideEffect(); auto rules = someRuleActions->getCopy(); if (auto str = boost::get(&id)) { @@ -169,16 +172,17 @@ static void rmRule(GlobalStateHolder > *someRuleActions, const boost:: g_outputBuffer = "Error: attempt to delete non-existing rule\n"; return; } - rules.erase(rules.begin()+*pos); + rules.erase(rules.begin() + *pos); } someRuleActions->setState(std::move(rules)); } -template -static void moveRuleToTop(GlobalStateHolder > *someRuleActions) { +template +static void moveRuleToTop(GlobalStateHolder>* someRuleActions) +{ setLuaSideEffect(); auto rules = someRuleActions->getCopy(); - if(rules.empty()) + if (rules.empty()) return; auto subject = *rules.rbegin(); rules.erase(std::prev(rules.end())); @@ -186,27 +190,28 @@ static void moveRuleToTop(GlobalStateHolder > *someRuleActions) { someRuleActions->setState(std::move(rules)); } -template -static void mvRule(GlobalStateHolder > *someRespRuleActions, unsigned int from, unsigned int to) { +template +static void mvRule(GlobalStateHolder>* someRespRuleActions, unsigned int from, unsigned int to) +{ setLuaSideEffect(); auto rules = someRespRuleActions->getCopy(); - if(from >= rules.size() || to > rules.size()) { + if (from >= rules.size() || to > rules.size()) { g_outputBuffer = "Error: attempt to move rules from/to invalid index\n"; return; } auto subject = rules[from]; - rules.erase(rules.begin()+from); - if(to > rules.size()) + rules.erase(rules.begin() + from); + if (to > rules.size()) rules.push_back(subject); else { - if(from < to) + if (from < to) --to; - rules.insert(rules.begin()+to, subject); + rules.insert(rules.begin() + to, subject); } someRespRuleActions->setState(std::move(rules)); } -template +template static std::vector getTopRules(const std::vector& rules, unsigned int top) { std::vector> counts; @@ -218,8 +223,7 @@ static std::vector getTopRules(const std::vector& rules, unsigned int top) pos++; } - sort(counts.begin(), counts.end(), [](const decltype(counts)::value_type& a, - const decltype(counts)::value_type& b) { + sort(counts.begin(), counts.end(), [](const decltype(counts)::value_type& a, const decltype(counts)::value_type& b) { return b.first < a.first; }); @@ -238,7 +242,7 @@ static std::vector getTopRules(const std::vector& rules, unsigned int top) return results; } -template +template static LuaArray toLuaArray(std::vector&& rules) { LuaArray results; @@ -313,49 +317,49 @@ void setupLuaRules(LuaContext& luaCtx) return makeRule(var, "makeRule"); }); - luaCtx.registerFunction::*)()const>("toString", [](const std::shared_ptr& rule) { return rule->toString(); }); + luaCtx.registerFunction::*)() const>("toString", [](const std::shared_ptr& rule) { return rule->toString(); }); - luaCtx.registerFunction::*)()const>("getMatches", [](const std::shared_ptr& rule) { return rule->d_matches.load(); }); + luaCtx.registerFunction::*)() const>("getMatches", [](const std::shared_ptr& rule) { return rule->d_matches.load(); }); - luaCtx.registerFunction(DNSDistRuleAction::*)()const>("getSelector", [](const DNSDistRuleAction& rule) { return rule.d_rule; }); + luaCtx.registerFunction (DNSDistRuleAction::*)() const>("getSelector", [](const DNSDistRuleAction& rule) { return rule.d_rule; }); - luaCtx.registerFunction(DNSDistRuleAction::*)()const>("getAction", [](const DNSDistRuleAction& rule) { return rule.d_action; }); + luaCtx.registerFunction (DNSDistRuleAction::*)() const>("getAction", [](const DNSDistRuleAction& rule) { return rule.d_action; }); - luaCtx.registerFunction(DNSDistResponseRuleAction::*)()const>("getSelector", [](const DNSDistResponseRuleAction& rule) { return rule.d_rule; }); + luaCtx.registerFunction (DNSDistResponseRuleAction::*)() const>("getSelector", [](const DNSDistResponseRuleAction& rule) { return rule.d_rule; }); - luaCtx.registerFunction(DNSDistResponseRuleAction::*)()const>("getAction", [](const DNSDistResponseRuleAction& rule) { return rule.d_action; }); + luaCtx.registerFunction (DNSDistResponseRuleAction::*)() const>("getAction", [](const DNSDistResponseRuleAction& rule) { return rule.d_action; }); luaCtx.writeFunction("showResponseRules", [](boost::optional vars) { - showRules(&g_respruleactions, vars); - }); + showRules(&g_respruleactions, vars); + }); luaCtx.writeFunction("rmResponseRule", [](boost::variant id) { - rmRule(&g_respruleactions, id); - }); + rmRule(&g_respruleactions, id); + }); luaCtx.writeFunction("mvResponseRuleToTop", []() { - moveRuleToTop(&g_respruleactions); - }); + moveRuleToTop(&g_respruleactions); + }); luaCtx.writeFunction("mvResponseRule", [](unsigned int from, unsigned int to) { - mvRule(&g_respruleactions, from, to); - }); + mvRule(&g_respruleactions, from, to); + }); luaCtx.writeFunction("showCacheHitResponseRules", [](boost::optional vars) { - showRules(&g_cachehitrespruleactions, vars); - }); + showRules(&g_cachehitrespruleactions, vars); + }); luaCtx.writeFunction("rmCacheHitResponseRule", [](boost::variant id) { - rmRule(&g_cachehitrespruleactions, id); - }); + rmRule(&g_cachehitrespruleactions, id); + }); luaCtx.writeFunction("mvCacheHitResponseRuleToTop", []() { - moveRuleToTop(&g_cachehitrespruleactions); - }); + moveRuleToTop(&g_cachehitrespruleactions); + }); luaCtx.writeFunction("mvCacheHitResponseRule", [](unsigned int from, unsigned int to) { - mvRule(&g_cachehitrespruleactions, from, to); - }); + mvRule(&g_cachehitrespruleactions, from, to); + }); luaCtx.writeFunction("showCacheInsertedResponseRules", [](boost::optional vars) { showRules(&g_cacheInsertedRespRuleActions, vars); @@ -374,53 +378,53 @@ void setupLuaRules(LuaContext& luaCtx) }); luaCtx.writeFunction("showSelfAnsweredResponseRules", [](boost::optional vars) { - showRules(&g_selfansweredrespruleactions, vars); - }); + showRules(&g_selfansweredrespruleactions, vars); + }); luaCtx.writeFunction("rmSelfAnsweredResponseRule", [](boost::variant id) { - rmRule(&g_selfansweredrespruleactions, id); - }); + rmRule(&g_selfansweredrespruleactions, id); + }); luaCtx.writeFunction("mvSelfAnsweredResponseRuleToTop", []() { - moveRuleToTop(&g_selfansweredrespruleactions); - }); + moveRuleToTop(&g_selfansweredrespruleactions); + }); luaCtx.writeFunction("mvSelfAnsweredResponseRule", [](unsigned int from, unsigned int to) { - mvRule(&g_selfansweredrespruleactions, from, to); - }); + mvRule(&g_selfansweredrespruleactions, from, to); + }); luaCtx.writeFunction("rmRule", [](boost::variant id) { - rmRule(&g_ruleactions, id); - }); + rmRule(&g_ruleactions, id); + }); luaCtx.writeFunction("mvRuleToTop", []() { - moveRuleToTop(&g_ruleactions); - }); + moveRuleToTop(&g_ruleactions); + }); luaCtx.writeFunction("mvRule", [](unsigned int from, unsigned int to) { - mvRule(&g_ruleactions, from, to); - }); + mvRule(&g_ruleactions, from, to); + }); luaCtx.writeFunction("clearRules", []() { - setLuaSideEffect(); - g_ruleactions.modify([](decltype(g_ruleactions)::value_type& ruleactions) { - ruleactions.clear(); - }); + setLuaSideEffect(); + g_ruleactions.modify([](decltype(g_ruleactions)::value_type& ruleactions) { + ruleactions.clear(); }); + }); luaCtx.writeFunction("setRules", [](const LuaArray>& newruleactions) { - setLuaSideEffect(); - g_ruleactions.modify([newruleactions](decltype(g_ruleactions)::value_type& gruleactions) { - gruleactions.clear(); - for (const auto& pair : newruleactions) { - const auto& newruleaction = pair.second; - if (newruleaction->d_action) { - auto rule = newruleaction->d_rule; - gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_name, newruleaction->d_id, newruleaction->d_creationOrder}); - } - } - }); + setLuaSideEffect(); + g_ruleactions.modify([newruleactions](decltype(g_ruleactions)::value_type& gruleactions) { + gruleactions.clear(); + for (const auto& pair : newruleactions) { + const auto& newruleaction = pair.second; + if (newruleaction->d_action) { + auto rule = newruleaction->d_rule; + gruleactions.push_back({std::move(rule), newruleaction->d_action, newruleaction->d_name, newruleaction->d_id, newruleaction->d_creationOrder}); + } + } }); + }); luaCtx.writeFunction("getRule", [](boost::variant selector) -> boost::optional { auto rules = g_ruleactions.getLocal(); @@ -509,39 +513,39 @@ void setupLuaRules(LuaContext& luaCtx) luaCtx.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional ipv4trunc, boost::optional ipv6trunc, boost::optional burst, boost::optional expiration, boost::optional cleanupDelay, boost::optional scanFraction, boost::optional shards) { return std::shared_ptr(new MaxQPSIPRule(qps, (burst ? *burst : qps), (ipv4trunc ? *ipv4trunc : 32), (ipv6trunc ? *ipv6trunc : 64), (expiration ? *expiration : 300), (cleanupDelay ? *cleanupDelay : 60), (scanFraction ? *scanFraction : 10), (shards ? *shards : 10))); - }); + }); luaCtx.writeFunction("MaxQPSRule", [](unsigned int qps, boost::optional burst) { - if(!burst) - return std::shared_ptr(new MaxQPSRule(qps)); - else - return std::shared_ptr(new MaxQPSRule(qps, *burst)); - }); + if (!burst) + return std::shared_ptr(new MaxQPSRule(qps)); + else + return std::shared_ptr(new MaxQPSRule(qps, *burst)); + }); luaCtx.writeFunction("RegexRule", [](const std::string& str) { - return std::shared_ptr(new RegexRule(str)); - }); + return std::shared_ptr(new RegexRule(str)); + }); #ifdef HAVE_DNS_OVER_HTTPS luaCtx.writeFunction("HTTPHeaderRule", [](const std::string& header, const std::string& regex) { - return std::shared_ptr(new HTTPHeaderRule(header, regex)); - }); + return std::shared_ptr(new HTTPHeaderRule(header, regex)); + }); luaCtx.writeFunction("HTTPPathRule", [](const std::string& path) { - return std::shared_ptr(new HTTPPathRule(path)); - }); + return std::shared_ptr(new HTTPPathRule(path)); + }); luaCtx.writeFunction("HTTPPathRegexRule", [](const std::string& regex) { - return std::shared_ptr(new HTTPPathRegexRule(regex)); - }); + return std::shared_ptr(new HTTPPathRegexRule(regex)); + }); #endif #ifdef HAVE_RE2 luaCtx.writeFunction("RE2Rule", [](const std::string& str) { - return std::shared_ptr(new RE2Rule(str)); - }); + return std::shared_ptr(new RE2Rule(str)); + }); #endif luaCtx.writeFunction("SNIRule", [](const std::string& name) { - return std::shared_ptr(new SNIRule(name)); + return std::shared_ptr(new SNIRule(name)); }); luaCtx.writeFunction("SuffixMatchNodeRule", qnameSuffixRule); @@ -565,175 +569,175 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new NetmaskGroupRule(nmg, src ? *src : true, quiet ? *quiet : false)); }); - luaCtx.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { - setLuaNoSideEffect(); - unsigned int times = times_ ? *times_ : 100000; - DNSName suffix(suffix_ ? *suffix_ : "powerdns.com"); - struct item { - PacketBuffer packet; - InternalQueryState ids; - }; - vector items; - items.reserve(1000); - for (int n = 0; n < 1000; ++n) { - struct item i; - i.ids.qname = DNSName(std::to_string(dns_random_uint32())); - i.ids.qname += suffix; - i.ids.qtype = dns_random(0xff); - i.ids.qclass = QClass::IN; - i.ids.protocol = dnsdist::Protocol::DoUDP; - i.ids.origRemote = ComboAddress("127.0.0.1"); - i.ids.origRemote.sin4.sin_addr.s_addr = random(); - i.ids.queryRealTime.start(); - GenericDNSPacketWriter pw(i.packet, i.ids.qname, i.ids.qtype); - items.push_back(std::move(i)); - } + luaCtx.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { + setLuaNoSideEffect(); + unsigned int times = times_ ? *times_ : 100000; + DNSName suffix(suffix_ ? *suffix_ : "powerdns.com"); + struct item + { + PacketBuffer packet; + InternalQueryState ids; + }; + vector items; + items.reserve(1000); + for (int n = 0; n < 1000; ++n) { + struct item i; + i.ids.qname = DNSName(std::to_string(dns_random_uint32())); + i.ids.qname += suffix; + i.ids.qtype = dns_random(0xff); + i.ids.qclass = QClass::IN; + i.ids.protocol = dnsdist::Protocol::DoUDP; + i.ids.origRemote = ComboAddress("127.0.0.1"); + i.ids.origRemote.sin4.sin_addr.s_addr = random(); + i.ids.queryRealTime.start(); + GenericDNSPacketWriter pw(i.packet, i.ids.qname, i.ids.qtype); + items.push_back(std::move(i)); + } - int matches = 0; - ComboAddress dummy("127.0.0.1"); - StopWatch sw; - sw.start(); - for (unsigned int n = 0; n < times; ++n) { - item& i = items[n % items.size()]; - DNSQuestion dq(i.ids, i.packet); + int matches = 0; + ComboAddress dummy("127.0.0.1"); + StopWatch sw; + sw.start(); + for (unsigned int n = 0; n < times; ++n) { + item& i = items[n % items.size()]; + DNSQuestion dq(i.ids, i.packet); - if (rule->matches(&dq)) { - matches++; - } + if (rule->matches(&dq)) { + matches++; } - double udiff = sw.udiff(); - g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f us\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str(); - - }); + } + double udiff = sw.udiff(); + g_outputBuffer = (boost::format("Had %d matches out of %d, %.1f qps, in %.1f us\n") % matches % times % (1000000 * (1.0 * times / udiff)) % udiff).str(); + }); luaCtx.writeFunction("AllRule", []() { - return std::shared_ptr(new AllRule()); - }); + return std::shared_ptr(new AllRule()); + }); luaCtx.writeFunction("ProbaRule", [](double proba) { - return std::shared_ptr(new ProbaRule(proba)); - }); + return std::shared_ptr(new ProbaRule(proba)); + }); luaCtx.writeFunction("QNameRule", [](const std::string& qname) { - return std::shared_ptr(new QNameRule(DNSName(qname))); - }); + return std::shared_ptr(new QNameRule(DNSName(qname))); + }); luaCtx.writeFunction("QNameSuffixRule", qnameSuffixRule); luaCtx.writeFunction("QTypeRule", [](boost::variant str) { - uint16_t qtype; - if (auto dir = boost::get(&str)) { - qtype = *dir; - } - else { - string val = boost::get(str); - qtype = QType::chartocode(val.c_str()); - if (!qtype) { - throw std::runtime_error("Unable to convert '"+val+"' to a DNS type"); - } + uint16_t qtype; + if (auto dir = boost::get(&str)) { + qtype = *dir; + } + else { + string val = boost::get(str); + qtype = QType::chartocode(val.c_str()); + if (!qtype) { + throw std::runtime_error("Unable to convert '" + val + "' to a DNS type"); } - return std::shared_ptr(new QTypeRule(qtype)); - }); + } + return std::shared_ptr(new QTypeRule(qtype)); + }); luaCtx.writeFunction("QClassRule", [](uint64_t c) { - checkParameterBound("QClassRule", c, std::numeric_limits::max()); - return std::shared_ptr(new QClassRule(c)); - }); + checkParameterBound("QClassRule", c, std::numeric_limits::max()); + return std::shared_ptr(new QClassRule(c)); + }); luaCtx.writeFunction("OpcodeRule", [](uint64_t code) { - checkParameterBound("OpcodeRule", code, std::numeric_limits::max()); - return std::shared_ptr(new OpcodeRule(code)); - }); + checkParameterBound("OpcodeRule", code, std::numeric_limits::max()); + return std::shared_ptr(new OpcodeRule(code)); + }); luaCtx.writeFunction("AndRule", [](const LuaArray>& a) { - return std::shared_ptr(new AndRule(a)); - }); + return std::shared_ptr(new AndRule(a)); + }); luaCtx.writeFunction("OrRule", [](const LuaArray>& a) { - return std::shared_ptr(new OrRule(a)); - }); + return std::shared_ptr(new OrRule(a)); + }); luaCtx.writeFunction("DSTPortRule", [](uint64_t port) { - checkParameterBound("DSTPortRule", port, std::numeric_limits::max()); - return std::shared_ptr(new DSTPortRule(port)); - }); + checkParameterBound("DSTPortRule", port, std::numeric_limits::max()); + return std::shared_ptr(new DSTPortRule(port)); + }); luaCtx.writeFunction("TCPRule", [](bool tcp) { - return std::shared_ptr(new TCPRule(tcp)); - }); + return std::shared_ptr(new TCPRule(tcp)); + }); luaCtx.writeFunction("DNSSECRule", []() { - return std::shared_ptr(new DNSSECRule()); - }); + return std::shared_ptr(new DNSSECRule()); + }); luaCtx.writeFunction("NotRule", [](const std::shared_ptr& rule) { - return std::shared_ptr(new NotRule(rule)); - }); + return std::shared_ptr(new NotRule(rule)); + }); luaCtx.writeFunction("RecordsCountRule", [](uint64_t section, uint64_t minCount, uint64_t maxCount) { - checkParameterBound("RecordsCountRule", section, std::numeric_limits::max()); - checkParameterBound("RecordsCountRule", minCount, std::numeric_limits::max()); - checkParameterBound("RecordsCountRule", maxCount, std::numeric_limits::max()); - return std::shared_ptr(new RecordsCountRule(section, minCount, maxCount)); - }); + checkParameterBound("RecordsCountRule", section, std::numeric_limits::max()); + checkParameterBound("RecordsCountRule", minCount, std::numeric_limits::max()); + checkParameterBound("RecordsCountRule", maxCount, std::numeric_limits::max()); + return std::shared_ptr(new RecordsCountRule(section, minCount, maxCount)); + }); luaCtx.writeFunction("RecordsTypeCountRule", [](uint64_t section, uint64_t type, uint64_t minCount, uint64_t maxCount) { - checkParameterBound("RecordsTypeCountRule", section, std::numeric_limits::max()); - checkParameterBound("RecordsTypeCountRule", type, std::numeric_limits::max()); - checkParameterBound("RecordsTypeCountRule", minCount, std::numeric_limits::max()); - checkParameterBound("RecordsTypeCountRule", maxCount, std::numeric_limits::max()); - return std::shared_ptr(new RecordsTypeCountRule(section, type, minCount, maxCount)); - }); + checkParameterBound("RecordsTypeCountRule", section, std::numeric_limits::max()); + checkParameterBound("RecordsTypeCountRule", type, std::numeric_limits::max()); + checkParameterBound("RecordsTypeCountRule", minCount, std::numeric_limits::max()); + checkParameterBound("RecordsTypeCountRule", maxCount, std::numeric_limits::max()); + return std::shared_ptr(new RecordsTypeCountRule(section, type, minCount, maxCount)); + }); luaCtx.writeFunction("TrailingDataRule", []() { - return std::shared_ptr(new TrailingDataRule()); - }); + return std::shared_ptr(new TrailingDataRule()); + }); luaCtx.writeFunction("QNameLabelsCountRule", [](uint64_t minLabelsCount, uint64_t maxLabelsCount) { - checkParameterBound("QNameLabelsCountRule", minLabelsCount, std::numeric_limits::max()); - checkParameterBound("QNameLabelsCountRule", maxLabelsCount, std::numeric_limits::max()); - return std::shared_ptr(new QNameLabelsCountRule(minLabelsCount, maxLabelsCount)); - }); + checkParameterBound("QNameLabelsCountRule", minLabelsCount, std::numeric_limits::max()); + checkParameterBound("QNameLabelsCountRule", maxLabelsCount, std::numeric_limits::max()); + return std::shared_ptr(new QNameLabelsCountRule(minLabelsCount, maxLabelsCount)); + }); luaCtx.writeFunction("QNameWireLengthRule", [](uint64_t min, uint64_t max) { - return std::shared_ptr(new QNameWireLengthRule(min, max)); - }); + return std::shared_ptr(new QNameWireLengthRule(min, max)); + }); luaCtx.writeFunction("RCodeRule", [](uint64_t rcode) { - checkParameterBound("RCodeRule", rcode, std::numeric_limits::max()); - return std::shared_ptr(new RCodeRule(rcode)); - }); + checkParameterBound("RCodeRule", rcode, std::numeric_limits::max()); + return std::shared_ptr(new RCodeRule(rcode)); + }); luaCtx.writeFunction("ERCodeRule", [](uint64_t rcode) { - checkParameterBound("ERCodeRule", rcode, std::numeric_limits::max()); - return std::shared_ptr(new ERCodeRule(rcode)); - }); + checkParameterBound("ERCodeRule", rcode, std::numeric_limits::max()); + return std::shared_ptr(new ERCodeRule(rcode)); + }); luaCtx.writeFunction("EDNSVersionRule", [](uint64_t version) { - checkParameterBound("EDNSVersionRule", version, std::numeric_limits::max()); - return std::shared_ptr(new EDNSVersionRule(version)); - }); + checkParameterBound("EDNSVersionRule", version, std::numeric_limits::max()); + return std::shared_ptr(new EDNSVersionRule(version)); + }); luaCtx.writeFunction("EDNSOptionRule", [](uint64_t optcode) { - checkParameterBound("EDNSOptionRule", optcode, std::numeric_limits::max()); - return std::shared_ptr(new EDNSOptionRule(optcode)); - }); + checkParameterBound("EDNSOptionRule", optcode, std::numeric_limits::max()); + return std::shared_ptr(new EDNSOptionRule(optcode)); + }); luaCtx.writeFunction("showRules", [](boost::optional vars) { - showRules(&g_ruleactions, vars); - }); + showRules(&g_ruleactions, vars); + }); luaCtx.writeFunction("RDRule", []() { - return std::shared_ptr(new RDRule()); - }); + return std::shared_ptr(new RDRule()); + }); luaCtx.writeFunction("TagRule", [](const std::string& tag, boost::optional value) { - return std::shared_ptr(new TagRule(tag, std::move(value))); - }); + return std::shared_ptr(new TagRule(tag, std::move(value))); + }); luaCtx.writeFunction("TimedIPSetRule", []() { - return std::shared_ptr(new TimedIPSetRule()); - }); + return std::shared_ptr(new TimedIPSetRule()); + }); luaCtx.writeFunction("PoolAvailableRule", [](const std::string& poolname) { return std::shared_ptr(new PoolAvailableRule(poolname)); @@ -743,56 +747,56 @@ void setupLuaRules(LuaContext& luaCtx) return std::shared_ptr(new PoolOutstandingRule(poolname, limit)); }); - luaCtx.registerFunction::*)()>("clear", [](std::shared_ptr tisr) { - tisr->clear(); - }); + luaCtx.registerFunction::*)()>("clear", [](std::shared_ptr tisr) { + tisr->clear(); + }); - luaCtx.registerFunction::*)()>("cleanup", [](std::shared_ptr tisr) { - tisr->cleanup(); - }); + luaCtx.registerFunction::*)()>("cleanup", [](std::shared_ptr tisr) { + tisr->cleanup(); + }); - luaCtx.registerFunction::*)(const ComboAddress& ca, int t)>("add", [](std::shared_ptr tisr, const ComboAddress& ca, int t) { - tisr->add(ca, time(0)+t); - }); + luaCtx.registerFunction::*)(const ComboAddress& ca, int t)>("add", [](std::shared_ptr tisr, const ComboAddress& ca, int t) { + tisr->add(ca, time(0) + t); + }); - luaCtx.registerFunction(std::shared_ptr::*)()>("slice", [](std::shared_ptr tisr) { - return std::dynamic_pointer_cast(tisr); - }); - luaCtx.registerFunction::*)()>("__tostring", [](std::shared_ptr tisr) { - tisr->toString(); - }); + luaCtx.registerFunction (std::shared_ptr::*)()>("slice", [](std::shared_ptr tisr) { + return std::dynamic_pointer_cast(tisr); + }); + luaCtx.registerFunction::*)()>("__tostring", [](std::shared_ptr tisr) { + tisr->toString(); + }); luaCtx.writeFunction("QNameSetRule", [](const DNSNameSet& names) { - return std::shared_ptr(new QNameSetRule(names)); - }); + return std::shared_ptr(new QNameSetRule(names)); + }); #if defined(HAVE_LMDB) || defined(HAVE_CDB) luaCtx.writeFunction("KeyValueStoreLookupRule", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey) { - return std::shared_ptr(new KeyValueStoreLookupRule(kvs, lookupKey)); - }); + return std::shared_ptr(new KeyValueStoreLookupRule(kvs, lookupKey)); + }); luaCtx.writeFunction("KeyValueStoreRangeLookupRule", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey) { - return std::shared_ptr(new KeyValueStoreRangeLookupRule(kvs, lookupKey)); - }); + return std::shared_ptr(new KeyValueStoreRangeLookupRule(kvs, lookupKey)); + }); #endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */ luaCtx.writeFunction("LuaRule", [](LuaRule::func_t func) { - return std::shared_ptr(new LuaRule(func)); - }); + return std::shared_ptr(new LuaRule(func)); + }); luaCtx.writeFunction("LuaFFIRule", [](LuaFFIRule::func_t func) { - return std::shared_ptr(new LuaFFIRule(func)); - }); + return std::shared_ptr(new LuaFFIRule(func)); + }); luaCtx.writeFunction("LuaFFIPerThreadRule", [](const std::string& code) { - return std::shared_ptr(new LuaFFIPerThreadRule(code)); - }); + return std::shared_ptr(new LuaFFIPerThreadRule(code)); + }); luaCtx.writeFunction("ProxyProtocolValueRule", [](uint8_t type, boost::optional value) { - return std::shared_ptr(new ProxyProtocolValueRule(type, std::move(value))); - }); + return std::shared_ptr(new ProxyProtocolValueRule(type, std::move(value))); + }); luaCtx.writeFunction("PayloadSizeRule", [](const std::string& comparison, uint16_t size) { return std::shared_ptr(new PayloadSizeRule(comparison, size)); - }); + }); } diff --git a/pdns/dnsdistdist/dnsdist-lua-vars.cc b/pdns/dnsdistdist/dnsdist-lua-vars.cc index 89927b7245..e237204220 100644 --- a/pdns/dnsdistdist/dnsdist-lua-vars.cc +++ b/pdns/dnsdistdist/dnsdist-lua-vars.cc @@ -23,96 +23,23 @@ #include "dnsdist-lua.hh" #include "ednsoptions.hh" -#undef BADSIG // signal.h SIG_ERR +#undef BADSIG // signal.h SIG_ERR void setupLuaVars(LuaContext& luaCtx) { - luaCtx.writeVariable("DNSAction", LuaAssociativeTable{ - {"Drop", (int)DNSAction::Action::Drop}, - {"Nxdomain", (int)DNSAction::Action::Nxdomain}, - {"Refused", (int)DNSAction::Action::Refused}, - {"Spoof", (int)DNSAction::Action::Spoof}, - {"SpoofPacket", (int)DNSAction::Action::SpoofPacket}, - {"SpoofRaw", (int)DNSAction::Action::SpoofRaw}, - {"Allow", (int)DNSAction::Action::Allow}, - {"HeaderModify", (int)DNSAction::Action::HeaderModify}, - {"Pool", (int)DNSAction::Action::Pool}, - {"None",(int)DNSAction::Action::None}, - {"NoOp",(int)DNSAction::Action::NoOp}, - {"Delay", (int)DNSAction::Action::Delay}, - {"Truncate", (int)DNSAction::Action::Truncate}, - {"ServFail", (int)DNSAction::Action::ServFail}, - {"NoRecurse", (int)DNSAction::Action::NoRecurse} - }); + luaCtx.writeVariable("DNSAction", LuaAssociativeTable{{"Drop", (int)DNSAction::Action::Drop}, {"Nxdomain", (int)DNSAction::Action::Nxdomain}, {"Refused", (int)DNSAction::Action::Refused}, {"Spoof", (int)DNSAction::Action::Spoof}, {"SpoofPacket", (int)DNSAction::Action::SpoofPacket}, {"SpoofRaw", (int)DNSAction::Action::SpoofRaw}, {"Allow", (int)DNSAction::Action::Allow}, {"HeaderModify", (int)DNSAction::Action::HeaderModify}, {"Pool", (int)DNSAction::Action::Pool}, {"None", (int)DNSAction::Action::None}, {"NoOp", (int)DNSAction::Action::NoOp}, {"Delay", (int)DNSAction::Action::Delay}, {"Truncate", (int)DNSAction::Action::Truncate}, {"ServFail", (int)DNSAction::Action::ServFail}, {"NoRecurse", (int)DNSAction::Action::NoRecurse}}); - luaCtx.writeVariable("DNSResponseAction", LuaAssociativeTable{ - {"Allow", (int)DNSResponseAction::Action::Allow }, - {"Delay", (int)DNSResponseAction::Action::Delay }, - {"Drop", (int)DNSResponseAction::Action::Drop }, - {"HeaderModify", (int)DNSResponseAction::Action::HeaderModify }, - {"ServFail", (int)DNSResponseAction::Action::ServFail }, - {"Truncate", (int)DNSResponseAction::Action::Truncate }, - {"None", (int)DNSResponseAction::Action::None } - }); + luaCtx.writeVariable("DNSResponseAction", LuaAssociativeTable{{"Allow", (int)DNSResponseAction::Action::Allow}, {"Delay", (int)DNSResponseAction::Action::Delay}, {"Drop", (int)DNSResponseAction::Action::Drop}, {"HeaderModify", (int)DNSResponseAction::Action::HeaderModify}, {"ServFail", (int)DNSResponseAction::Action::ServFail}, {"Truncate", (int)DNSResponseAction::Action::Truncate}, {"None", (int)DNSResponseAction::Action::None}}); - luaCtx.writeVariable("DNSClass", LuaAssociativeTable{ - {"IN", QClass::IN }, - {"CHAOS", QClass::CHAOS }, - {"NONE", QClass::NONE }, - {"ANY", QClass::ANY } - }); + luaCtx.writeVariable("DNSClass", LuaAssociativeTable{{"IN", QClass::IN}, {"CHAOS", QClass::CHAOS}, {"NONE", QClass::NONE}, {"ANY", QClass::ANY}}); - luaCtx.writeVariable("DNSOpcode", LuaAssociativeTable{ - {"Query", Opcode::Query }, - {"IQuery", Opcode::IQuery }, - {"Status", Opcode::Status }, - {"Notify", Opcode::Notify }, - {"Update", Opcode::Update } - }); + luaCtx.writeVariable("DNSOpcode", LuaAssociativeTable{{"Query", Opcode::Query}, {"IQuery", Opcode::IQuery}, {"Status", Opcode::Status}, {"Notify", Opcode::Notify}, {"Update", Opcode::Update}}); - luaCtx.writeVariable("DNSSection", LuaAssociativeTable{ - {"Question", 0 }, - {"Answer", 1 }, - {"Authority", 2 }, - {"Additional",3 } - }); + luaCtx.writeVariable("DNSSection", LuaAssociativeTable{{"Question", 0}, {"Answer", 1}, {"Authority", 2}, {"Additional", 3}}); - luaCtx.writeVariable("EDNSOptionCode", LuaAssociativeTable{ - {"NSID", EDNSOptionCode::NSID }, - {"DAU", EDNSOptionCode::DAU }, - {"DHU", EDNSOptionCode::DHU }, - {"N3U", EDNSOptionCode::N3U }, - {"ECS", EDNSOptionCode::ECS }, - {"EXPIRE", EDNSOptionCode::EXPIRE }, - {"COOKIE", EDNSOptionCode::COOKIE }, - {"TCPKEEPALIVE", EDNSOptionCode::TCPKEEPALIVE }, - {"PADDING", EDNSOptionCode::PADDING }, - {"CHAIN", EDNSOptionCode::CHAIN }, - {"KEYTAG", EDNSOptionCode::KEYTAG } - }); + luaCtx.writeVariable("EDNSOptionCode", LuaAssociativeTable{{"NSID", EDNSOptionCode::NSID}, {"DAU", EDNSOptionCode::DAU}, {"DHU", EDNSOptionCode::DHU}, {"N3U", EDNSOptionCode::N3U}, {"ECS", EDNSOptionCode::ECS}, {"EXPIRE", EDNSOptionCode::EXPIRE}, {"COOKIE", EDNSOptionCode::COOKIE}, {"TCPKEEPALIVE", EDNSOptionCode::TCPKEEPALIVE}, {"PADDING", EDNSOptionCode::PADDING}, {"CHAIN", EDNSOptionCode::CHAIN}, {"KEYTAG", EDNSOptionCode::KEYTAG}}); - luaCtx.writeVariable("DNSRCode", LuaAssociativeTable{ - {"NOERROR", RCode::NoError }, - {"FORMERR", RCode::FormErr }, - {"SERVFAIL", RCode::ServFail }, - {"NXDOMAIN", RCode::NXDomain }, - {"NOTIMP", RCode::NotImp }, - {"REFUSED", RCode::Refused }, - {"YXDOMAIN", RCode::YXDomain }, - {"YXRRSET", RCode::YXRRSet }, - {"NXRRSET", RCode::NXRRSet }, - {"NOTAUTH", RCode::NotAuth }, - {"NOTZONE", RCode::NotZone }, - {"BADVERS", ERCode::BADVERS }, - {"BADSIG", ERCode::BADSIG }, - {"BADKEY", ERCode::BADKEY }, - {"BADTIME", ERCode::BADTIME }, - {"BADMODE", ERCode::BADMODE }, - {"BADNAME", ERCode::BADNAME }, - {"BADALG", ERCode::BADALG }, - {"BADTRUNC", ERCode::BADTRUNC }, - {"BADCOOKIE",ERCode::BADCOOKIE } - }); + luaCtx.writeVariable("DNSRCode", LuaAssociativeTable{{"NOERROR", RCode::NoError}, {"FORMERR", RCode::FormErr}, {"SERVFAIL", RCode::ServFail}, {"NXDOMAIN", RCode::NXDomain}, {"NOTIMP", RCode::NotImp}, {"REFUSED", RCode::Refused}, {"YXDOMAIN", RCode::YXDomain}, {"YXRRSET", RCode::YXRRSet}, {"NXRRSET", RCode::NXRRSet}, {"NOTAUTH", RCode::NotAuth}, {"NOTZONE", RCode::NotZone}, {"BADVERS", ERCode::BADVERS}, {"BADSIG", ERCode::BADSIG}, {"BADKEY", ERCode::BADKEY}, {"BADTIME", ERCode::BADTIME}, {"BADMODE", ERCode::BADMODE}, {"BADNAME", ERCode::BADNAME}, {"BADALG", ERCode::BADALG}, {"BADTRUNC", ERCode::BADTRUNC}, {"BADCOOKIE", ERCode::BADCOOKIE}}); LuaAssociativeTable dd; for (const auto& n : QType::names) { @@ -121,9 +48,9 @@ void setupLuaVars(LuaContext& luaCtx) luaCtx.writeVariable("DNSQType", dd); #ifdef HAVE_DNSCRYPT - luaCtx.writeVariable("DNSCryptExchangeVersion", LuaAssociativeTable{ - { "VERSION1", DNSCryptExchangeVersion::VERSION1 }, - { "VERSION2", DNSCryptExchangeVersion::VERSION2 }, - }); + luaCtx.writeVariable("DNSCryptExchangeVersion", LuaAssociativeTable{ + {"VERSION1", DNSCryptExchangeVersion::VERSION1}, + {"VERSION2", DNSCryptExchangeVersion::VERSION2}, + }); #endif } diff --git a/pdns/dnsdistdist/dnsdist-lua.hh b/pdns/dnsdistdist/dnsdist-lua.hh index 5c35c3fb9d..8a6363300a 100644 --- a/pdns/dnsdistdist/dnsdist-lua.hh +++ b/pdns/dnsdistdist/dnsdist-lua.hh @@ -38,7 +38,8 @@ void setResponseHeadersFromConfig(dnsheader& dnsheader, const ResponseConfig& co class SpoofAction : public DNSAction { public: - SpoofAction(const vector& addrs): d_addrs(addrs) + SpoofAction(const vector& addrs) : + d_addrs(addrs) { for (const auto& addr : d_addrs) { if (addr.isIPv4()) { @@ -54,15 +55,18 @@ public: } } - SpoofAction(const DNSName& cname): d_cname(cname) + SpoofAction(const DNSName& cname) : + d_cname(cname) { } - SpoofAction(const char* rawresponse, size_t len): d_raw(rawresponse, rawresponse + len) + SpoofAction(const char* rawresponse, size_t len) : + d_raw(rawresponse, rawresponse + len) { } - SpoofAction(const vector& raws, std::optional typeForAny): d_rawResponses(raws), d_rawTypeForAny(typeForAny) + SpoofAction(const vector& raws, std::optional typeForAny) : + d_rawResponses(raws), d_rawTypeForAny(typeForAny) { } @@ -78,8 +82,8 @@ public: ret += "raw bytes "; } else { - for(const auto& a : d_addrs) - ret += a.toString()+" "; + for (const auto& a : d_addrs) + ret += a.toString() + " "; } return ret; } @@ -105,7 +109,8 @@ class LimitTTLResponseAction : public DNSResponseAction, public boost::noncopyab public: LimitTTLResponseAction() {} - LimitTTLResponseAction(uint32_t min, uint32_t max = std::numeric_limits::max(), const std::unordered_set& types = {}) : d_types(types), d_min(min), d_max(max) + LimitTTLResponseAction(uint32_t min, uint32_t max = std::numeric_limits::max(), const std::unordered_set& types = {}) : + d_types(types), d_min(min), d_max(max) { } @@ -126,7 +131,7 @@ public: } return ttl; }; - editDNSPacketTTL(reinterpret_cast(dr->getMutableData().data()), dr->getData().size(), visitor); + editDNSPacketTTL(reinterpret_cast(dr->getMutableData().data()), dr->getData().size(), visitor); return DNSResponseAction::Action::None; } @@ -147,7 +152,7 @@ public: } result += "]"; } - result += + ")"; + result += +")"; return result; } @@ -157,9 +162,12 @@ private: uint32_t d_max{std::numeric_limits::max()}; }; -template using LuaArray = std::vector>; -template using LuaAssociativeTable = std::unordered_map; -template using LuaTypeOrArrayOf = boost::variant>; +template +using LuaArray = std::vector>; +template +using LuaAssociativeTable = std::unordered_map; +template +using LuaTypeOrArrayOf = boost::variant>; using luaruleparams_t = LuaAssociativeTable; using nmts_t = NetmaskTree; @@ -195,8 +203,9 @@ void setupLuaLoadBalancingContext(LuaContext& luaCtx); * * returns: -1 if type wasn't compatible, 0 if not found or number of element(s) found */ -template -static inline int getOptionalValue(boost::optional& vars, const std::string& key, T& value, bool warnOnWrongType = true) { +template +static inline int getOptionalValue(boost::optional& vars, const std::string& key, T& value, bool warnOnWrongType = true) +{ /* nothing found, nothing to return */ if (!vars) { return 0; @@ -205,7 +214,8 @@ static inline int getOptionalValue(boost::optional& vars, const std::string& if (vars->count(key)) { try { value = boost::get((*vars)[key]); - } catch (const boost::bad_get& e) { + } + catch (const boost::bad_get& e) { /* key is there but isn't compatible */ if (warnOnWrongType) { warnlog("Invalid type for key '%s' - ignored", key); @@ -217,8 +227,9 @@ static inline int getOptionalValue(boost::optional& vars, const std::string& return vars->erase(key); } -template -static inline int getOptionalIntegerValue(const std::string& func, boost::optional& vars, const std::string& key, T& value) { +template +static inline int getOptionalIntegerValue(const std::string& func, boost::optional& vars, const std::string& key, T& value) +{ std::string valueStr; auto ret = getOptionalValue(vars, key, valueStr, true); if (ret == 1) { @@ -233,8 +244,9 @@ static inline int getOptionalIntegerValue(const std::string& func, boost::option return ret; } -template -static inline void checkAllParametersConsumed(const std::string& func, const boost::optional& vars) { +template +static inline void checkAllParametersConsumed(const std::string& func, const boost::optional& vars) +{ /* no vars */ if (!vars) { return; diff --git a/pdns/dnsdistdist/dnsdist-rings.cc b/pdns/dnsdistdist/dnsdist-rings.cc index b97b44e645..7ab00f1b7b 100644 --- a/pdns/dnsdistdist/dnsdist-rings.cc +++ b/pdns/dnsdistdist/dnsdist-rings.cc @@ -65,7 +65,8 @@ void Rings::setNumberOfLockRetries(size_t retries) { if (d_numberOfShards <= 1) { d_nbLockTries = 0; - } else { + } + else { d_nbLockTries = retries; } } @@ -92,23 +93,23 @@ size_t Rings::numDistinctRequestors() return s.size(); } -std::unordered_map>> Rings::getTopBandwidth(unsigned int numentries) +std::unordered_map>> Rings::getTopBandwidth(unsigned int numentries) { map counts; - uint64_t total=0; + uint64_t total = 0; for (const auto& shard : d_shards) { { auto rl = shard->queryRing.lock(); - for(const auto& q : *rl) { + for (const auto& q : *rl) { counts[q.requestor] += q.size; - total+=q.size; + total += q.size; } } { auto rl = shard->respRing.lock(); - for(const auto& r : *rl) { + for (const auto& r : *rl) { counts[r.requestor] += r.size; - total+=r.size; + total += r.size; } } } @@ -116,30 +117,29 @@ std::unordered_map>> Rings::getTopBand typedef vector> ret_t; ret_t rcounts; rcounts.reserve(counts.size()); - for(const auto& p : counts) + for (const auto& p : counts) rcounts.push_back({p.second, p.first}); numentries = rcounts.size() < numentries ? rcounts.size() : numentries; - partial_sort(rcounts.begin(), rcounts.begin()+numentries, rcounts.end(), [](const ret_t::value_type&a, const ret_t::value_type&b) - { - return(b.first < a.first); - }); - std::unordered_map>> ret; + partial_sort(rcounts.begin(), rcounts.begin() + numentries, rcounts.end(), [](const ret_t::value_type& a, const ret_t::value_type& b) { + return (b.first < a.first); + }); + std::unordered_map>> ret; uint64_t rest = 0; int count = 1; - for(const auto& rc : rcounts) { + for (const auto& rc : rcounts) { if (count == static_cast(numentries + 1)) { - rest+=rc.first; + rest += rc.first; } else { - ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); + ret.insert({count++, {rc.second.toString(), rc.first, 100.0 * rc.first / total}}); } } if (total > 0) { - ret.insert({count, {"Rest", rest, 100.0*rest/total}}); + ret.insert({count, {"Rest", rest, 100.0 * rest / total}}); } else { - ret.insert({count, {"Rest", rest, 100.0 }}); + ret.insert({count, {"Rest", rest, 100.0}}); } return ret; @@ -170,7 +170,7 @@ size_t Rings::loadFromFile(const std::string& filepath, const struct timespec& n isResponse = true; } else { - cerr<<"skipping line with "< timeStr; stringtok(timeStr, parts.at(idx++), "."); if (timeStr.size() != 2) { - cerr<<"skipping invalid time "<> respRing; }; - Rings(size_t capacity=10000, size_t numberOfShards=10, size_t nbLockTries=5, bool keepLockingStats=false): d_blockingQueryInserts(0), d_blockingResponseInserts(0), d_deferredQueryInserts(0), d_deferredResponseInserts(0), d_nbQueryEntries(0), d_nbResponseEntries(0), d_currentShardId(0), d_capacity(capacity), d_numberOfShards(numberOfShards), d_nbLockTries(nbLockTries), d_keepLockingStats(keepLockingStats) + Rings(size_t capacity = 10000, size_t numberOfShards = 10, size_t nbLockTries = 5, bool keepLockingStats = false) : + d_blockingQueryInserts(0), d_blockingResponseInserts(0), d_deferredQueryInserts(0), d_deferredResponseInserts(0), d_nbQueryEntries(0), d_nbResponseEntries(0), d_currentShardId(0), d_capacity(capacity), d_numberOfShards(numberOfShards), d_nbLockTries(nbLockTries), d_keepLockingStats(keepLockingStats) { } - std::unordered_map > > getTopBandwidth(unsigned int numentries); + std::unordered_map>> getTopBandwidth(unsigned int numentries); size_t numDistinctRequestors(); /* this function should not be called after init() has been called */ void setCapacity(size_t newCapacity, size_t numberOfShards); @@ -201,7 +203,7 @@ struct Rings { return d_recordResponses; } - std::vector > d_shards; + std::vector> d_shards; pdns::stat_t d_blockingQueryInserts; pdns::stat_t d_blockingResponseInserts; pdns::stat_t d_deferredQueryInserts; diff --git a/pdns/dnsdistdist/dnsdist-snmp.cc b/pdns/dnsdistdist/dnsdist-snmp.cc index 856fccb111..6081d11f9e 100644 --- a/pdns/dnsdistdist/dnsdist-snmp.cc +++ b/pdns/dnsdistdist/dnsdist-snmp.cc @@ -15,46 +15,46 @@ DNSDistSNMPAgent* g_snmpAgent{nullptr}; #define DNSDIST_TRAPS_OID DNSDIST_OID, 10, 0 #define DNSDIST_TRAP_OBJECTS_OID DNSDIST_OID, 11 -static const oid queriesOID[] = { DNSDIST_STATS_OID, 1 }; -static const oid responsesOID[] = { DNSDIST_STATS_OID, 2 }; -static const oid servfailResponsesOID[] = { DNSDIST_STATS_OID, 3 }; -static const oid aclDropsOID[] = { DNSDIST_STATS_OID, 4 }; +static const oid queriesOID[] = {DNSDIST_STATS_OID, 1}; +static const oid responsesOID[] = {DNSDIST_STATS_OID, 2}; +static const oid servfailResponsesOID[] = {DNSDIST_STATS_OID, 3}; +static const oid aclDropsOID[] = {DNSDIST_STATS_OID, 4}; // 5 was BlockFilter, removed in 1.2.0 -static const oid ruleDropOID[] = { DNSDIST_STATS_OID, 6 }; -static const oid ruleNXDomainOID[] = { DNSDIST_STATS_OID, 7 }; -static const oid ruleRefusedOID[] = { DNSDIST_STATS_OID, 8 }; -static const oid selfAnsweredOID[] = { DNSDIST_STATS_OID, 9 }; -static const oid downstreamTimeoutsOID[] = { DNSDIST_STATS_OID, 10 }; -static const oid downstreamSendErrorsOID[] = { DNSDIST_STATS_OID, 11 }; -static const oid truncFailOID[] = { DNSDIST_STATS_OID, 12 }; -static const oid noPolicyOID[] = { DNSDIST_STATS_OID, 13 }; -static const oid latency0_1OID[] = { DNSDIST_STATS_OID, 14 }; -static const oid latency1_10OID[] = { DNSDIST_STATS_OID, 15 }; -static const oid latency10_50OID[] = { DNSDIST_STATS_OID, 16 }; -static const oid latency50_100OID[] = { DNSDIST_STATS_OID, 17 }; -static const oid latency100_1000OID[] = { DNSDIST_STATS_OID, 18 }; -static const oid latencySlowOID[] = { DNSDIST_STATS_OID, 19 }; -static const oid latencyAvg100OID[] = { DNSDIST_STATS_OID, 20 }; -static const oid latencyAvg1000OID[] = { DNSDIST_STATS_OID, 21 }; -static const oid latencyAvg10000OID[] = { DNSDIST_STATS_OID, 22 }; -static const oid latencyAvg1000000OID[] = { DNSDIST_STATS_OID, 23 }; -static const oid uptimeOID[] = { DNSDIST_STATS_OID, 24 }; -static const oid realMemoryUsageOID[] = { DNSDIST_STATS_OID, 25 }; -static const oid nonCompliantQueriesOID[] = { DNSDIST_STATS_OID, 26 }; -static const oid nonCompliantResponsesOID[] = { DNSDIST_STATS_OID, 27 }; -static const oid rdQueriesOID[] = { DNSDIST_STATS_OID, 28 }; -static const oid emptyQueriesOID[] = { DNSDIST_STATS_OID, 29 }; -static const oid cacheHitsOID[] = { DNSDIST_STATS_OID, 30 }; -static const oid cacheMissesOID[] = { DNSDIST_STATS_OID, 31 }; -static const oid cpuUserMSecOID[] = { DNSDIST_STATS_OID, 32 }; -static const oid cpuSysMSecOID[] = { DNSDIST_STATS_OID, 33 }; -static const oid fdUsageOID[] = { DNSDIST_STATS_OID, 34 }; -static const oid dynBlockedOID[] = { DNSDIST_STATS_OID, 35 }; -static const oid dynBlockedNMGSizeOID[] = { DNSDIST_STATS_OID, 36 }; -static const oid ruleServFailOID[] = { DNSDIST_STATS_OID, 37 }; -static const oid securityStatusOID[] = { DNSDIST_STATS_OID, 38 }; -static const oid specialMemoryUsageOID[] = { DNSDIST_STATS_OID, 39 }; -static const oid ruleTruncatedOID[] = { DNSDIST_STATS_OID, 40 }; +static const oid ruleDropOID[] = {DNSDIST_STATS_OID, 6}; +static const oid ruleNXDomainOID[] = {DNSDIST_STATS_OID, 7}; +static const oid ruleRefusedOID[] = {DNSDIST_STATS_OID, 8}; +static const oid selfAnsweredOID[] = {DNSDIST_STATS_OID, 9}; +static const oid downstreamTimeoutsOID[] = {DNSDIST_STATS_OID, 10}; +static const oid downstreamSendErrorsOID[] = {DNSDIST_STATS_OID, 11}; +static const oid truncFailOID[] = {DNSDIST_STATS_OID, 12}; +static const oid noPolicyOID[] = {DNSDIST_STATS_OID, 13}; +static const oid latency0_1OID[] = {DNSDIST_STATS_OID, 14}; +static const oid latency1_10OID[] = {DNSDIST_STATS_OID, 15}; +static const oid latency10_50OID[] = {DNSDIST_STATS_OID, 16}; +static const oid latency50_100OID[] = {DNSDIST_STATS_OID, 17}; +static const oid latency100_1000OID[] = {DNSDIST_STATS_OID, 18}; +static const oid latencySlowOID[] = {DNSDIST_STATS_OID, 19}; +static const oid latencyAvg100OID[] = {DNSDIST_STATS_OID, 20}; +static const oid latencyAvg1000OID[] = {DNSDIST_STATS_OID, 21}; +static const oid latencyAvg10000OID[] = {DNSDIST_STATS_OID, 22}; +static const oid latencyAvg1000000OID[] = {DNSDIST_STATS_OID, 23}; +static const oid uptimeOID[] = {DNSDIST_STATS_OID, 24}; +static const oid realMemoryUsageOID[] = {DNSDIST_STATS_OID, 25}; +static const oid nonCompliantQueriesOID[] = {DNSDIST_STATS_OID, 26}; +static const oid nonCompliantResponsesOID[] = {DNSDIST_STATS_OID, 27}; +static const oid rdQueriesOID[] = {DNSDIST_STATS_OID, 28}; +static const oid emptyQueriesOID[] = {DNSDIST_STATS_OID, 29}; +static const oid cacheHitsOID[] = {DNSDIST_STATS_OID, 30}; +static const oid cacheMissesOID[] = {DNSDIST_STATS_OID, 31}; +static const oid cpuUserMSecOID[] = {DNSDIST_STATS_OID, 32}; +static const oid cpuSysMSecOID[] = {DNSDIST_STATS_OID, 33}; +static const oid fdUsageOID[] = {DNSDIST_STATS_OID, 34}; +static const oid dynBlockedOID[] = {DNSDIST_STATS_OID, 35}; +static const oid dynBlockedNMGSizeOID[] = {DNSDIST_STATS_OID, 36}; +static const oid ruleServFailOID[] = {DNSDIST_STATS_OID, 37}; +static const oid securityStatusOID[] = {DNSDIST_STATS_OID, 38}; +static const oid specialMemoryUsageOID[] = {DNSDIST_STATS_OID, 39}; +static const oid ruleTruncatedOID[] = {DNSDIST_STATS_OID, 40}; static std::unordered_map s_statsMap; @@ -202,40 +202,40 @@ static void registerGauge64Stat(const char* name, const oid statOID[], size_t st } /* column number definitions for table backendStatTable */ -#define COLUMN_BACKENDID 1 -#define COLUMN_BACKENDNAME 2 -#define COLUMN_BACKENDLATENCY 3 -#define COLUMN_BACKENDWEIGHT 4 -#define COLUMN_BACKENDOUTSTANDING 5 -#define COLUMN_BACKENDQPSLIMIT 6 -#define COLUMN_BACKENDREUSED 7 -#define COLUMN_BACKENDSTATE 8 -#define COLUMN_BACKENDADDRESS 9 -#define COLUMN_BACKENDPOOLS 10 -#define COLUMN_BACKENDQPS 11 -#define COLUMN_BACKENDQUERIES 12 -#define COLUMN_BACKENDORDER 13 - -static const oid backendStatTableOID[] = { DNSDIST_STATS_TABLE_OID }; -static const oid backendNameOID[] = { DNSDIST_STATS_TABLE_OID, 1, 2 }; -static const oid backendStateOID[] = { DNSDIST_STATS_TABLE_OID, 1, 8}; -static const oid backendAddressOID[] = { DNSDIST_STATS_TABLE_OID, 1, 9}; - -static const oid socketFamilyOID[] = { DNSDIST_TRAP_OBJECTS_OID, 1, 0 }; -static const oid socketProtocolOID[] = { DNSDIST_TRAP_OBJECTS_OID, 2, 0 }; -static const oid fromAddressOID[] = { DNSDIST_TRAP_OBJECTS_OID, 3, 0 }; -static const oid toAddressOID[] = { DNSDIST_TRAP_OBJECTS_OID, 4, 0 }; -static const oid queryTypeOID[] = { DNSDIST_TRAP_OBJECTS_OID, 5, 0 }; -static const oid querySizeOID[] = { DNSDIST_TRAP_OBJECTS_OID, 6, 0 }; -static const oid queryIDOID[] = { DNSDIST_TRAP_OBJECTS_OID, 7, 0 }; -static const oid qNameOID[] = { DNSDIST_TRAP_OBJECTS_OID, 8, 0 }; -static const oid qClassOID[] = { DNSDIST_TRAP_OBJECTS_OID, 9, 0 }; -static const oid qTypeOID[] = { DNSDIST_TRAP_OBJECTS_OID, 10, 0 }; -static const oid trapReasonOID[] = { DNSDIST_TRAP_OBJECTS_OID, 11, 0 }; - -static const oid backendStatusChangeTrapOID[] = { DNSDIST_TRAPS_OID, 1 }; -static const oid actionTrapOID[] = { DNSDIST_TRAPS_OID, 2 }; -static const oid customTrapOID[] = { DNSDIST_TRAPS_OID, 3 }; +#define COLUMN_BACKENDID 1 +#define COLUMN_BACKENDNAME 2 +#define COLUMN_BACKENDLATENCY 3 +#define COLUMN_BACKENDWEIGHT 4 +#define COLUMN_BACKENDOUTSTANDING 5 +#define COLUMN_BACKENDQPSLIMIT 6 +#define COLUMN_BACKENDREUSED 7 +#define COLUMN_BACKENDSTATE 8 +#define COLUMN_BACKENDADDRESS 9 +#define COLUMN_BACKENDPOOLS 10 +#define COLUMN_BACKENDQPS 11 +#define COLUMN_BACKENDQUERIES 12 +#define COLUMN_BACKENDORDER 13 + +static const oid backendStatTableOID[] = {DNSDIST_STATS_TABLE_OID}; +static const oid backendNameOID[] = {DNSDIST_STATS_TABLE_OID, 1, 2}; +static const oid backendStateOID[] = {DNSDIST_STATS_TABLE_OID, 1, 8}; +static const oid backendAddressOID[] = {DNSDIST_STATS_TABLE_OID, 1, 9}; + +static const oid socketFamilyOID[] = {DNSDIST_TRAP_OBJECTS_OID, 1, 0}; +static const oid socketProtocolOID[] = {DNSDIST_TRAP_OBJECTS_OID, 2, 0}; +static const oid fromAddressOID[] = {DNSDIST_TRAP_OBJECTS_OID, 3, 0}; +static const oid toAddressOID[] = {DNSDIST_TRAP_OBJECTS_OID, 4, 0}; +static const oid queryTypeOID[] = {DNSDIST_TRAP_OBJECTS_OID, 5, 0}; +static const oid querySizeOID[] = {DNSDIST_TRAP_OBJECTS_OID, 6, 0}; +static const oid queryIDOID[] = {DNSDIST_TRAP_OBJECTS_OID, 7, 0}; +static const oid qNameOID[] = {DNSDIST_TRAP_OBJECTS_OID, 8, 0}; +static const oid qClassOID[] = {DNSDIST_TRAP_OBJECTS_OID, 9, 0}; +static const oid qTypeOID[] = {DNSDIST_TRAP_OBJECTS_OID, 10, 0}; +static const oid trapReasonOID[] = {DNSDIST_TRAP_OBJECTS_OID, 11, 0}; + +static const oid backendStatusChangeTrapOID[] = {DNSDIST_TRAPS_OID, 1}; +static const oid actionTrapOID[] = {DNSDIST_TRAPS_OID, 2}; +static const oid customTrapOID[] = {DNSDIST_TRAPS_OID, 3}; static servers_t s_servers; static size_t s_currentServerIdx = 0; @@ -249,7 +249,7 @@ static netsnmp_variable_list* backendStatTable_get_next_data_point(void** loop_c return NULL; } - *my_data_context = (void*) (s_servers[s_currentServerIdx]).get(); + *my_data_context = (void*)(s_servers[s_currentServerIdx]).get(); snmp_set_var_typed_integer(put_index_data, ASN_UNSIGNED, s_currentServerIdx); s_currentServerIdx++; @@ -289,7 +289,7 @@ static int backendStatTable_handler(netsnmp_mib_handler* handler, case MODE_GET: for (request = requests; request; request = request->next) { netsnmp_table_request_info* table_info = netsnmp_extract_table_info(request); - const DownstreamState* server = (const DownstreamState*) netsnmp_extract_iterator_context(request); + const DownstreamState* server = (const DownstreamState*)netsnmp_extract_iterator_context(request); if (!server) { continue; @@ -321,8 +321,7 @@ static int backendStatTable_handler(netsnmp_mib_handler* handler, case COLUMN_BACKENDREUSED: DNSDistSNMPAgent::setCounter64Value(request, server->reuseds.load()); break; - case COLUMN_BACKENDSTATE: - { + case COLUMN_BACKENDSTATE: { std::string state(server->getStatus()); snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, @@ -330,8 +329,7 @@ static int backendStatTable_handler(netsnmp_mib_handler* handler, state.size()); break; } - case COLUMN_BACKENDADDRESS: - { + case COLUMN_BACKENDADDRESS: { std::string addr(server->d_config.remote.toStringWithPort()); snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, @@ -339,12 +337,11 @@ static int backendStatTable_handler(netsnmp_mib_handler* handler, addr.size()); break; } - case COLUMN_BACKENDPOOLS: - { + case COLUMN_BACKENDPOOLS: { std::string pools; for (const auto& p : server->d_config.pools) { if (!pools.empty()) { - pools+=" "; + pools += " "; } pools += p; } @@ -388,8 +385,7 @@ bool DNSDistSNMPAgent::sendBackendStatusChangeTrap(const DownstreamState& dss) snmpTrapOID.size(), ASN_OBJECT_ID, backendStatusChangeTrapOID, - OID_LENGTH(backendStatusChangeTrapOID) * sizeof(oid)); - + OID_LENGTH(backendStatusChangeTrapOID) * sizeof(oid)); snmp_varlist_add_variable(&varList, backendNameOID, @@ -428,7 +424,7 @@ bool DNSDistSNMPAgent::sendCustomTrap(const std::string& reason) snmpTrapOID.size(), ASN_OBJECT_ID, customTrapOID, - OID_LENGTH(customTrapOID) * sizeof(oid)); + OID_LENGTH(customTrapOID) * sizeof(oid)); snmp_varlist_add_variable(&varList, trapReasonOID, @@ -452,10 +448,10 @@ bool DNSDistSNMPAgent::sendDNSTrap(const DNSQuestion& dq, const std::string& rea const uint32_t socketFamily = dq.ids.origRemote.isIPv4() ? 1 : 2; const uint32_t socketProtocol = dq.overTCP() ? 2 : 1; const uint32_t queryType = dq.getHeader()->qr ? 2 : 1; - const uint32_t querySize = (uint32_t) dq.getData().size(); - const uint32_t queryID = (uint32_t) ntohs(dq.getHeader()->id); - const uint32_t qType = (uint32_t) dq.ids.qtype; - const uint32_t qClass = (uint32_t) dq.ids.qclass; + const uint32_t querySize = (uint32_t)dq.getData().size(); + const uint32_t queryID = (uint32_t)ntohs(dq.getHeader()->id); + const uint32_t qType = (uint32_t)dq.ids.qtype; + const uint32_t qClass = (uint32_t)dq.ids.qclass; netsnmp_variable_list* varList = nullptr; @@ -464,7 +460,7 @@ bool DNSDistSNMPAgent::sendDNSTrap(const DNSQuestion& dq, const std::string& rea snmpTrapOID.size(), ASN_OBJECT_ID, actionTrapOID, - OID_LENGTH(actionTrapOID) * sizeof(oid)); + OID_LENGTH(actionTrapOID) * sizeof(oid)); snmp_varlist_add_variable(&varList, socketFamilyOID, @@ -549,7 +545,8 @@ bool DNSDistSNMPAgent::sendDNSTrap(const DNSQuestion& dq, const std::string& rea #endif /* HAVE_NET_SNMP */ } -DNSDistSNMPAgent::DNSDistSNMPAgent(const std::string& name, const std::string& daemonSocket): SNMPAgent(name, daemonSocket) +DNSDistSNMPAgent::DNSDistSNMPAgent(const std::string& name, const std::string& daemonSocket) : + SNMPAgent(name, daemonSocket) { #ifdef HAVE_NET_SNMP @@ -593,10 +590,9 @@ DNSDistSNMPAgent::DNSDistSNMPAgent(const std::string& name, const std::string& d registerGauge64Stat("securityStatus", securityStatusOID, OID_LENGTH(securityStatusOID), [](const std::string&) { return dnsdist::metrics::g_stats.securityStatus.load(); }); registerGauge64Stat("realMemoryUsage", realMemoryUsageOID, OID_LENGTH(realMemoryUsageOID), &getRealMemoryUsage); - netsnmp_table_registration_info* table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); netsnmp_table_helper_add_indexes(table_info, - ASN_GAUGE, /* index: backendId */ + ASN_GAUGE, /* index: backendId */ 0); table_info->min_column = COLUMN_BACKENDNAME; table_info->max_column = COLUMN_BACKENDORDER; diff --git a/pdns/dnsdistdist/dnsdist-snmp.hh b/pdns/dnsdistdist/dnsdist-snmp.hh index 283d43c6a5..7c1deff9b3 100644 --- a/pdns/dnsdistdist/dnsdist-snmp.hh +++ b/pdns/dnsdistdist/dnsdist-snmp.hh @@ -27,11 +27,11 @@ class DNSDistSNMPAgent; #include "dnsdist.hh" -class DNSDistSNMPAgent: public SNMPAgent +class DNSDistSNMPAgent : public SNMPAgent { public: DNSDistSNMPAgent(const std::string& name, const std::string& daemonSocket); bool sendBackendStatusChangeTrap(const DownstreamState&); bool sendCustomTrap(const std::string& reason); - bool sendDNSTrap(const DNSQuestion&, const std::string& reason=""); + bool sendDNSTrap(const DNSQuestion&, const std::string& reason = ""); }; diff --git a/pdns/dnsdistdist/dnsdist-web.cc b/pdns/dnsdistdist/dnsdist-web.cc index 066b5c177f..7462c43bf1 100644 --- a/pdns/dnsdistdist/dnsdist-web.cc +++ b/pdns/dnsdistdist/dnsdist-web.cc @@ -53,7 +53,7 @@ struct WebserverConfig NetmaskGroup acl; std::unique_ptr password; std::unique_ptr apiKey; - boost::optional > customHeaders; + boost::optional> customHeaders; bool apiRequiresAuthentication{true}; bool dashboardRequiresAuthentication{true}; bool statsRequireAuthentication{true}; @@ -99,13 +99,15 @@ std::string getWebserverConfig() class WebClientConnection { public: - WebClientConnection(const ComboAddress& client, int fd): d_client(client), d_socket(fd) + WebClientConnection(const ComboAddress& client, int fd) : + d_client(client), d_socket(fd) { if (!s_connManager.registerConnection()) { throw std::runtime_error("Too many concurrent web client connections"); } } - WebClientConnection(WebClientConnection&& rhs): d_client(rhs.d_client), d_socket(std::move(rhs.d_socket)) + WebClientConnection(WebClientConnection&& rhs) : + d_client(rhs.d_client), d_socket(std::move(rhs.d_socket)) { } @@ -138,87 +140,88 @@ private: static MetricDefinitionStorage s_metricDefinitions; std::map MetricDefinitionStorage::metrics{ - { "responses", MetricDefinition(PrometheusMetricType::counter, "Number of responses received from backends") }, - { "servfail-responses", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers received from backends") }, - { "queries", MetricDefinition(PrometheusMetricType::counter, "Number of received queries")}, - { "frontend-nxdomain", MetricDefinition(PrometheusMetricType::counter, "Number of NXDomain answers sent to clients")}, - { "frontend-servfail", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers sent to clients")}, - { "frontend-noerror", MetricDefinition(PrometheusMetricType::counter, "Number of NoError answers sent to clients")}, - { "acl-drops", MetricDefinition(PrometheusMetricType::counter, "Number of packets dropped because of the ACL")}, - { "rule-drop", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of a rule")}, - { "rule-nxdomain", MetricDefinition(PrometheusMetricType::counter, "Number of NXDomain answers returned because of a rule")}, - { "rule-refused", MetricDefinition(PrometheusMetricType::counter, "Number of Refused answers returned because of a rule")}, - { "rule-servfail", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers received because of a rule")}, - { "rule-truncated", MetricDefinition(PrometheusMetricType::counter, "Number of truncated answers returned because of a rule")}, - { "self-answered", MetricDefinition(PrometheusMetricType::counter, "Number of self-answered responses")}, - { "downstream-timeouts", MetricDefinition(PrometheusMetricType::counter, "Number of queries not answered in time by a backend")}, - { "downstream-send-errors", MetricDefinition(PrometheusMetricType::counter, "Number of errors when sending a query to a backend")}, - { "trunc-failures", MetricDefinition(PrometheusMetricType::counter, "Number of errors encountered while truncating an answer")}, - { "no-policy", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because no server was available")}, - { "latency0-1", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in less than 1ms")}, - { "latency1-10", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 1-10 ms")}, - { "latency10-50", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 10-50 ms")}, - { "latency50-100", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 50-100 ms")}, - { "latency100-1000", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 100-1000 ms")}, - { "latency-slow", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in more than 1 second")}, - { "latency-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 100 packets")}, - { "latency-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000 packets")}, - { "latency-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 10000 packets")}, - { "latency-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000000 packets")}, - { "latency-tcp-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over TCP")}, - { "latency-tcp-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over TCP")}, - { "latency-tcp-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over TCP")}, - { "latency-tcp-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over TCP")}, - { "latency-dot-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoT")}, - { "latency-dot-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoT")}, - { "latency-dot-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoT")}, - { "latency-dot-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoT")}, - { "latency-doh-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoH")}, - { "latency-doh-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoH")}, - { "latency-doh-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoH")}, - { "latency-doh-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoH")}, - { "latency-doq-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoQ")}, - { "latency-doq-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoQ")}, - { "latency-doq-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoQ")}, - { "latency-doq-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoQ")}, - { "uptime", MetricDefinition(PrometheusMetricType::gauge, "Uptime of the dnsdist process in seconds")}, - { "real-memory-usage", MetricDefinition(PrometheusMetricType::gauge, "Current memory usage in bytes")}, - { "noncompliant-queries", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped as non-compliant")}, - { "noncompliant-responses", MetricDefinition(PrometheusMetricType::counter, "Number of answers from a backend dropped as non-compliant")}, - { "rdqueries", MetricDefinition(PrometheusMetricType::counter, "Number of received queries with the recursion desired bit set")}, - { "empty-queries", MetricDefinition(PrometheusMetricType::counter, "Number of empty queries received from clients")}, - { "cache-hits", MetricDefinition(PrometheusMetricType::counter, "Number of times an answer was retrieved from cache")}, - { "cache-misses", MetricDefinition(PrometheusMetricType::counter, "Number of times an answer not found in the cache")}, - { "cpu-iowait", MetricDefinition(PrometheusMetricType::counter, "Time waiting for I/O to complete by the whole system, in units of USER_HZ")}, - { "cpu-user-msec", MetricDefinition(PrometheusMetricType::counter, "Milliseconds spent by dnsdist in the user state")}, - { "cpu-steal", MetricDefinition(PrometheusMetricType::counter, "Stolen time, which is the time spent by the whole system in other operating systems when running in a virtualized environment, in units of USER_HZ")}, - { "cpu-sys-msec", MetricDefinition(PrometheusMetricType::counter, "Milliseconds spent by dnsdist in the system state")}, - { "fd-usage", MetricDefinition(PrometheusMetricType::gauge, "Number of currently used file descriptors")}, - { "dyn-blocked", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of a dynamic block")}, - { "dyn-block-nmg-size", MetricDefinition(PrometheusMetricType::gauge, "Number of dynamic blocks entries") }, - { "security-status", MetricDefinition(PrometheusMetricType::gauge, "Security status of this software. 0=unknown, 1=OK, 2=upgrade recommended, 3=upgrade mandatory") }, - { "doh-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of DoH queries dropped because the internal pipe used to distribute queries was full") }, - { "doh-response-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of DoH responses dropped because the internal pipe used to distribute responses was full") }, - { "outgoing-doh-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of outgoing DoH queries dropped because the internal pipe used to distribute queries was full") }, - { "tcp-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP queries dropped because the internal pipe used to distribute queries was full") }, - { "tcp-cross-protocol-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP cross-protocol queries dropped because the internal pipe used to distribute queries was full") }, - { "tcp-cross-protocol-response-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP cross-protocol responses dropped because the internal pipe used to distribute queries was full") }, - { "udp-in-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp InErrors") }, - { "udp-noport-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp NoPorts") }, - { "udp-recvbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp RcvbufErrors") }, - { "udp-sndbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp SndbufErrors") }, - { "udp-in-csum-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp InCsumErrors") }, - { "udp6-in-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6InErrors") }, - { "udp6-recvbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6RcvbufErrors") }, - { "udp6-sndbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6SndbufErrors") }, - { "udp6-noport-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6NoPorts") }, - { "udp6-in-csum-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6InCsumErrors") }, - { "tcp-listen-overflows", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/netstat ListenOverflows") }, - { "proxy-protocol-invalid", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of an invalid Proxy Protocol header") }, + {"responses", MetricDefinition(PrometheusMetricType::counter, "Number of responses received from backends")}, + {"servfail-responses", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers received from backends")}, + {"queries", MetricDefinition(PrometheusMetricType::counter, "Number of received queries")}, + {"frontend-nxdomain", MetricDefinition(PrometheusMetricType::counter, "Number of NXDomain answers sent to clients")}, + {"frontend-servfail", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers sent to clients")}, + {"frontend-noerror", MetricDefinition(PrometheusMetricType::counter, "Number of NoError answers sent to clients")}, + {"acl-drops", MetricDefinition(PrometheusMetricType::counter, "Number of packets dropped because of the ACL")}, + {"rule-drop", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of a rule")}, + {"rule-nxdomain", MetricDefinition(PrometheusMetricType::counter, "Number of NXDomain answers returned because of a rule")}, + {"rule-refused", MetricDefinition(PrometheusMetricType::counter, "Number of Refused answers returned because of a rule")}, + {"rule-servfail", MetricDefinition(PrometheusMetricType::counter, "Number of SERVFAIL answers received because of a rule")}, + {"rule-truncated", MetricDefinition(PrometheusMetricType::counter, "Number of truncated answers returned because of a rule")}, + {"self-answered", MetricDefinition(PrometheusMetricType::counter, "Number of self-answered responses")}, + {"downstream-timeouts", MetricDefinition(PrometheusMetricType::counter, "Number of queries not answered in time by a backend")}, + {"downstream-send-errors", MetricDefinition(PrometheusMetricType::counter, "Number of errors when sending a query to a backend")}, + {"trunc-failures", MetricDefinition(PrometheusMetricType::counter, "Number of errors encountered while truncating an answer")}, + {"no-policy", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because no server was available")}, + {"latency0-1", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in less than 1ms")}, + {"latency1-10", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 1-10 ms")}, + {"latency10-50", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 10-50 ms")}, + {"latency50-100", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 50-100 ms")}, + {"latency100-1000", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in 100-1000 ms")}, + {"latency-slow", MetricDefinition(PrometheusMetricType::counter, "Number of queries answered in more than 1 second")}, + {"latency-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 100 packets")}, + {"latency-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000 packets")}, + {"latency-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 10000 packets")}, + {"latency-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency in microseconds of the last 1000000 packets")}, + {"latency-tcp-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over TCP")}, + {"latency-tcp-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over TCP")}, + {"latency-tcp-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over TCP")}, + {"latency-tcp-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over TCP")}, + {"latency-dot-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoT")}, + {"latency-dot-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoT")}, + {"latency-dot-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoT")}, + {"latency-dot-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoT")}, + {"latency-doh-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoH")}, + {"latency-doh-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoH")}, + {"latency-doh-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoH")}, + {"latency-doh-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoH")}, + {"latency-doq-avg100", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 100 packets received over DoQ")}, + {"latency-doq-avg1000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000 packets received over DoQ")}, + {"latency-doq-avg10000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 10000 packets received over DoQ")}, + {"latency-doq-avg1000000", MetricDefinition(PrometheusMetricType::gauge, "Average response latency, in microseconds, of the last 1000000 packets received over DoQ")}, + {"uptime", MetricDefinition(PrometheusMetricType::gauge, "Uptime of the dnsdist process in seconds")}, + {"real-memory-usage", MetricDefinition(PrometheusMetricType::gauge, "Current memory usage in bytes")}, + {"noncompliant-queries", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped as non-compliant")}, + {"noncompliant-responses", MetricDefinition(PrometheusMetricType::counter, "Number of answers from a backend dropped as non-compliant")}, + {"rdqueries", MetricDefinition(PrometheusMetricType::counter, "Number of received queries with the recursion desired bit set")}, + {"empty-queries", MetricDefinition(PrometheusMetricType::counter, "Number of empty queries received from clients")}, + {"cache-hits", MetricDefinition(PrometheusMetricType::counter, "Number of times an answer was retrieved from cache")}, + {"cache-misses", MetricDefinition(PrometheusMetricType::counter, "Number of times an answer not found in the cache")}, + {"cpu-iowait", MetricDefinition(PrometheusMetricType::counter, "Time waiting for I/O to complete by the whole system, in units of USER_HZ")}, + {"cpu-user-msec", MetricDefinition(PrometheusMetricType::counter, "Milliseconds spent by dnsdist in the user state")}, + {"cpu-steal", MetricDefinition(PrometheusMetricType::counter, "Stolen time, which is the time spent by the whole system in other operating systems when running in a virtualized environment, in units of USER_HZ")}, + {"cpu-sys-msec", MetricDefinition(PrometheusMetricType::counter, "Milliseconds spent by dnsdist in the system state")}, + {"fd-usage", MetricDefinition(PrometheusMetricType::gauge, "Number of currently used file descriptors")}, + {"dyn-blocked", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of a dynamic block")}, + {"dyn-block-nmg-size", MetricDefinition(PrometheusMetricType::gauge, "Number of dynamic blocks entries")}, + {"security-status", MetricDefinition(PrometheusMetricType::gauge, "Security status of this software. 0=unknown, 1=OK, 2=upgrade recommended, 3=upgrade mandatory")}, + {"doh-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of DoH queries dropped because the internal pipe used to distribute queries was full")}, + {"doh-response-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of DoH responses dropped because the internal pipe used to distribute responses was full")}, + {"outgoing-doh-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of outgoing DoH queries dropped because the internal pipe used to distribute queries was full")}, + {"tcp-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP queries dropped because the internal pipe used to distribute queries was full")}, + {"tcp-cross-protocol-query-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP cross-protocol queries dropped because the internal pipe used to distribute queries was full")}, + {"tcp-cross-protocol-response-pipe-full", MetricDefinition(PrometheusMetricType::counter, "Number of TCP cross-protocol responses dropped because the internal pipe used to distribute queries was full")}, + {"udp-in-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp InErrors")}, + {"udp-noport-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp NoPorts")}, + {"udp-recvbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp RcvbufErrors")}, + {"udp-sndbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp SndbufErrors")}, + {"udp-in-csum-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp InCsumErrors")}, + {"udp6-in-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6InErrors")}, + {"udp6-recvbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6RcvbufErrors")}, + {"udp6-sndbuf-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6SndbufErrors")}, + {"udp6-noport-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6NoPorts")}, + {"udp6-in-csum-errors", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/snmp6 Udp6InCsumErrors")}, + {"tcp-listen-overflows", MetricDefinition(PrometheusMetricType::counter, "From /proc/net/netstat ListenOverflows")}, + {"proxy-protocol-invalid", MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped because of an invalid Proxy Protocol header")}, }; #endif /* DISABLE_PROMETHEUS */ -bool addMetricDefinition(const dnsdist::prometheus::PrometheusMetricDefinition& def) { +bool addMetricDefinition(const dnsdist::prometheus::PrometheusMetricDefinition& def) +{ #ifndef DISABLE_PROMETHEUS return MetricDefinitionStorage::addMetricDefinition(def); #else @@ -341,7 +344,7 @@ static bool handleAuthorization(const YaHTTP::Request& req) if (isAnAPIRequest(req)) { /* Access to the API requires a valid API key */ - if (!config->apiRequiresAuthentication || checkAPIKey(req, config->apiKey)) { + if (!config->apiRequiresAuthentication || checkAPIKey(req, config->apiKey)) { return true; } @@ -399,14 +402,14 @@ static void handleCORS(const YaHTTP::Request& req, YaHTTP::Response& resp) } } -static void addSecurityHeaders(YaHTTP::Response& resp, const boost::optional >& customHeaders) +static void addSecurityHeaders(YaHTTP::Response& resp, const boost::optional>& customHeaders) { - static const std::vector > headers = { - { "X-Content-Type-Options", "nosniff" }, - { "X-Frame-Options", "deny" }, - { "X-Permitted-Cross-Domain-Policies", "none" }, - { "X-XSS-Protection", "1; mode=block" }, - { "Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'" }, + static const std::vector> headers = { + {"X-Content-Type-Options", "nosniff"}, + {"X-Frame-Options", "deny"}, + {"X-Permitted-Cross-Domain-Policies", "none"}, + {"X-XSS-Protection", "1; mode=block"}, + {"Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'"}, }; for (const auto& h : headers) { @@ -420,7 +423,7 @@ static void addSecurityHeaders(YaHTTP::Response& resp, const boost::optional >& customHeaders) +static void addCustomHeaders(YaHTTP::Response& resp, const boost::optional>& customHeaders) { if (!customHeaders) return; @@ -432,31 +435,31 @@ static void addCustomHeaders(YaHTTP::Response& resp, const boost::optional +template static json11::Json::array someResponseRulesToJson(GlobalStateHolder>* someResponseRules) { using namespace json11; Json::array responseRules; - int num=0; + int num = 0; auto localResponseRules = someResponseRules->getLocal(); responseRules.reserve(localResponseRules->size()); for (const auto& a : *localResponseRules) { responseRules.push_back(Json::object{ - {"id", num++}, - {"creationOrder", (double)a.d_creationOrder}, - {"uuid", boost::uuids::to_string(a.d_id)}, - {"name", a.d_name}, - {"matches", (double)a.d_rule->d_matches}, - {"rule", a.d_rule->toString()}, - {"action", a.d_action->toString()}, - }); + {"id", num++}, + {"creationOrder", (double)a.d_creationOrder}, + {"uuid", boost::uuids::to_string(a.d_id)}, + {"name", a.d_name}, + {"matches", (double)a.d_rule->d_matches}, + {"rule", a.d_rule->toString()}, + {"action", a.d_action->toString()}, + }); } return responseRules; } #ifndef DISABLE_PROMETHEUS -template -static void addRulesToPrometheusOutput(std::ostringstream& output, GlobalStateHolder >& rules) +template +static void addRulesToPrometheusOutput(std::ostringstream& output, GlobalStateHolder>& rules) { auto localRules = rules.getLocal(); for (const auto& entry : *localRules) { @@ -471,7 +474,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp) resp.status = 200; std::ostringstream output; - static const std::set metricBlacklist = { "special-memory-usage", "latency-count", "latency-sum" }; + static const std::set metricBlacklist = {"special-memory-usage", "latency-count", "latency-sum"}; { auto entries = dnsdist::metrics::g_stats.entries.read_lock(); for (const auto& entry : *entries) { @@ -505,7 +508,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp) // for these we have the help and types encoded in the sources // but we need to be careful about labels in custom metrics std::string helpName = prometheusMetricName.substr(0, prometheusMetricName.find('{')); - output << "# HELP " << helpName << " " << metricDetails.description << "\n"; + output << "# HELP " << helpName << " " << metricDetails.description << "\n"; output << "# TYPE " << helpName << " " << prometheusTypeName << "\n"; output << prometheusMetricName << " "; @@ -547,6 +550,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp) auto states = g_dstates.getLocal(); const string statesbase = "dnsdist_server_"; + // clang-format off output << "# HELP " << statesbase << "status " << "Whether this backend is up (1) or down (0)" << "\n"; output << "# TYPE " << statesbase << "status " << "gauge" << "\n"; output << "# HELP " << statesbase << "queries " << "Amount of queries relayed to server" << "\n"; @@ -910,6 +914,7 @@ static void handlePrometheus(const YaHTTP::Request& req, YaHTTP::Response& resp) resp.body = output.str(); resp.headers["Content-Type"] = "text/plain"; + // clang-format on } #endif /* DISABLE_PROMETHEUS */ @@ -924,11 +929,14 @@ static void addStatsToJSONObject(Json::object& obj) } if (const auto& val = std::get_if(&entry.d_value)) { obj.emplace(entry.d_name, (double)(*val)->load()); - } else if (const auto& adval = std::get_if*>(&entry.d_value)) { + } + else if (const auto& adval = std::get_if*>(&entry.d_value)) { obj.emplace(entry.d_name, (*adval)->load()); - } else if (const auto& dval = std::get_if(&entry.d_value)) { + } + else if (const auto& dval = std::get_if(&entry.d_value)) { obj.emplace(entry.d_name, (**dval)); - } else if (const auto& func = std::get_if(&entry.d_value)) { + } + else if (const auto& func = std::get_if(&entry.d_value)) { obj.emplace(entry.d_name, (double)(*func)(entry.d_name)); } } @@ -948,13 +956,12 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) const string& command = req.getvars.at("command"); if (command == "stats") { - auto obj=Json::object { - { "packetcache-hits", 0}, - { "packetcache-misses", 0}, - { "over-capacity-drops", 0 }, - { "too-old-drops", 0 }, - { "server-policy", g_policy.getLocal()->getName()} - }; + auto obj = Json::object{ + {"packetcache-hits", 0}, + {"packetcache-misses", 0}, + {"over-capacity-drops", 0}, + {"too-old-drops", 0}, + {"server-policy", g_policy.getLocal()->getName()}}; addStatsToJSONObject(obj); @@ -968,7 +975,7 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) auto nmg = g_dynblockNMG.getLocal(); struct timespec now; gettime(&now); - for (const auto& entry: *nmg) { + for (const auto& entry : *nmg) { if (!(now < entry.second.until)) { continue; } @@ -982,13 +989,12 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"blocks", static_cast(counter)}, {"action", DNSAction::typeToString(entry.second.action != DNSAction::Action::None ? entry.second.action : g_dynBlockAction)}, {"warning", entry.second.warning}, - {"ebpf", entry.second.bpf} - }; + {"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](const SuffixMatchTree& node) { if (!(now < node.d_value.until)) { return; } @@ -1001,8 +1007,7 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"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)}, - {"ebpf", node.d_value.bpf} - }; + {"ebpf", node.d_value.bpf}}; obj.emplace(dom, thing); }); #endif /* DISABLE_DYNBLOCKS */ @@ -1016,19 +1021,17 @@ static void handleJSONStats(const YaHTTP::Request& req, YaHTTP::Response& resp) struct timespec now; gettime(&now); for (const auto& dynbpf : g_dynBPFFilters) { - std::vector > addrStats = dynbpf->getAddrStats(); + std::vector> addrStats = dynbpf->getAddrStats(); for (const auto& entry : addrStats) { - Json::object thing - { - {"seconds", (double)(std::get<2>(entry).tv_sec - now.tv_sec)}, - {"blocks", (double)(std::get<1>(entry))} - }; - obj.emplace(std::get<0>(entry).toString(), thing ); + Json::object thing{ + {"seconds", (double)(std::get<2>(entry).tv_sec - now.tv_sec)}, + {"blocks", (double)(std::get<1>(entry))}}; + obj.emplace(std::get<0>(entry).toString(), thing); } } if (g_defaultBPFFilter) { auto nmg = g_dynblockNMG.getLocal(); - for (const auto& entry: *nmg) { + for (const auto& entry : *nmg) { if (!(now < entry.second.until) || !entry.second.bpf) { continue; } @@ -1069,11 +1072,11 @@ static void addServerToJSON(Json::array& servers, int id, const std::shared_ptr< Json::array pools; pools.reserve(a->d_config.pools.size()); - for (const auto& p: a->d_config.pools) { + for (const auto& p : a->d_config.pools) { pools.push_back(p); } - Json::object server { + Json::object server{ {"id", id}, {"name", a->getName()}, {"address", a->d_config.remote.toStringWithPort()}, @@ -1086,7 +1089,7 @@ static void addServerToJSON(Json::array& servers, int id, const std::shared_ptr< {"weight", (double)a->d_config.d_weight}, {"order", (double)a->d_config.order}, {"pools", std::move(pools)}, - {"latency", (double)(a->latencyUsec/1000.0)}, + {"latency", (double)(a->latencyUsec / 1000.0)}, {"queries", (double)a->queries}, {"responses", (double)a->responses}, {"nonCompliantResponses", (double)a->nonCompliantResponses}, @@ -1105,15 +1108,14 @@ static void addServerToJSON(Json::array& servers, int id, const std::shared_ptr< {"tcpAvgQueriesPerConnection", (double)a->tcpAvgQueriesPerConnection}, {"tcpAvgConnectionDuration", (double)a->tcpAvgConnectionDuration}, {"tlsResumptions", (double)a->tlsResumptions}, - {"tcpLatency", (double)(a->latencyUsecTCP/1000.0)}, + {"tcpLatency", (double)(a->latencyUsecTCP / 1000.0)}, {"healthCheckFailures", (double)(a->d_healthCheckMetrics.d_failures)}, {"healthCheckFailuresParsing", (double)(a->d_healthCheckMetrics.d_parseErrors)}, {"healthCheckFailuresTimeout", (double)(a->d_healthCheckMetrics.d_timeOuts)}, {"healthCheckFailuresNetwork", (double)(a->d_healthCheckMetrics.d_networkErrors)}, {"healthCheckFailuresMismatch", (double)(a->d_healthCheckMetrics.d_mismatchErrors)}, {"healthCheckFailuresInvalid", (double)(a->d_healthCheckMetrics.d_invalidResponseErrors)}, - {"dropRate", (double)a->dropRate} - }; + {"dropRate", (double)a->dropRate}}; /* sending a latency for a DOWN server doesn't make sense */ if (a->d_config.availability == DownstreamState::Availability::Down) { @@ -1146,33 +1148,33 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) for (const auto& front : g_frontends) { if (front->udpFD == -1 && front->tcpFD == -1) continue; - Json::object frontend { - { "id", num++ }, - { "address", front->local.toStringWithPort() }, - { "udp", front->udpFD >= 0 }, - { "tcp", front->tcpFD >= 0 }, - { "type", front->getType() }, - { "queries", (double) front->queries.load() }, - { "nonCompliantQueries", (double) front->nonCompliantQueries.load() }, - { "responses", (double) front->responses.load() }, - { "tcpDiedReadingQuery", (double) front->tcpDiedReadingQuery.load() }, - { "tcpDiedSendingResponse", (double) front->tcpDiedSendingResponse.load() }, - { "tcpGaveUp", (double) front->tcpGaveUp.load() }, - { "tcpClientTimeouts", (double) front->tcpClientTimeouts }, - { "tcpDownstreamTimeouts", (double) front->tcpDownstreamTimeouts }, - { "tcpCurrentConnections", (double) front->tcpCurrentConnections }, - { "tcpMaxConcurrentConnections", (double) front->tcpMaxConcurrentConnections }, - { "tcpAvgQueriesPerConnection", (double) front->tcpAvgQueriesPerConnection }, - { "tcpAvgConnectionDuration", (double) front->tcpAvgConnectionDuration }, - { "tlsNewSessions", (double) front->tlsNewSessions }, - { "tlsResumptions", (double) front->tlsResumptions }, - { "tlsUnknownTicketKey", (double) front->tlsUnknownTicketKey }, - { "tlsInactiveTicketKey", (double) front->tlsInactiveTicketKey }, - { "tls10Queries", (double) front->tls10queries }, - { "tls11Queries", (double) front->tls11queries }, - { "tls12Queries", (double) front->tls12queries }, - { "tls13Queries", (double) front->tls13queries }, - { "tlsUnknownQueries", (double) front->tlsUnknownqueries }, + Json::object frontend{ + {"id", num++}, + {"address", front->local.toStringWithPort()}, + {"udp", front->udpFD >= 0}, + {"tcp", front->tcpFD >= 0}, + {"type", front->getType()}, + {"queries", (double)front->queries.load()}, + {"nonCompliantQueries", (double)front->nonCompliantQueries.load()}, + {"responses", (double)front->responses.load()}, + {"tcpDiedReadingQuery", (double)front->tcpDiedReadingQuery.load()}, + {"tcpDiedSendingResponse", (double)front->tcpDiedSendingResponse.load()}, + {"tcpGaveUp", (double)front->tcpGaveUp.load()}, + {"tcpClientTimeouts", (double)front->tcpClientTimeouts}, + {"tcpDownstreamTimeouts", (double)front->tcpDownstreamTimeouts}, + {"tcpCurrentConnections", (double)front->tcpCurrentConnections}, + {"tcpMaxConcurrentConnections", (double)front->tcpMaxConcurrentConnections}, + {"tcpAvgQueriesPerConnection", (double)front->tcpAvgQueriesPerConnection}, + {"tcpAvgConnectionDuration", (double)front->tcpAvgConnectionDuration}, + {"tlsNewSessions", (double)front->tlsNewSessions}, + {"tlsResumptions", (double)front->tlsResumptions}, + {"tlsUnknownTicketKey", (double)front->tlsUnknownTicketKey}, + {"tlsInactiveTicketKey", (double)front->tlsInactiveTicketKey}, + {"tls10Queries", (double)front->tls10queries}, + {"tls11Queries", (double)front->tls11queries}, + {"tls12Queries", (double)front->tls12queries}, + {"tls13Queries", (double)front->tls13queries}, + {"tlsUnknownQueries", (double)front->tlsUnknownqueries}, }; const TLSErrorCounters* errorCounters = nullptr; if (front->tlsFrontend != nullptr) { @@ -1201,30 +1203,29 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) num = 0; for (const auto& doh : g_dohlocals) { dohs.emplace_back(Json::object{ - { "id", num++ }, - { "address", doh->d_tlsContext.d_addr.toStringWithPort() }, - { "http-connects", (double) doh->d_httpconnects }, - { "http1-queries", (double) doh->d_http1Stats.d_nbQueries }, - { "http2-queries", (double) doh->d_http2Stats.d_nbQueries }, - { "http1-200-responses", (double) doh->d_http1Stats.d_nb200Responses }, - { "http2-200-responses", (double) doh->d_http2Stats.d_nb200Responses }, - { "http1-400-responses", (double) doh->d_http1Stats.d_nb400Responses }, - { "http2-400-responses", (double) doh->d_http2Stats.d_nb400Responses }, - { "http1-403-responses", (double) doh->d_http1Stats.d_nb403Responses }, - { "http2-403-responses", (double) doh->d_http2Stats.d_nb403Responses }, - { "http1-500-responses", (double) doh->d_http1Stats.d_nb500Responses }, - { "http2-500-responses", (double) doh->d_http2Stats.d_nb500Responses }, - { "http1-502-responses", (double) doh->d_http1Stats.d_nb502Responses }, - { "http2-502-responses", (double) doh->d_http2Stats.d_nb502Responses }, - { "http1-other-responses", (double) doh->d_http1Stats.d_nbOtherResponses }, - { "http2-other-responses", (double) doh->d_http2Stats.d_nbOtherResponses }, - { "get-queries", (double) doh->d_getqueries }, - { "post-queries", (double) doh->d_postqueries }, - { "bad-requests", (double) doh->d_badrequests }, - { "error-responses", (double) doh->d_errorresponses }, - { "redirect-responses", (double) doh->d_redirectresponses }, - { "valid-responses", (double) doh->d_validresponses } - }); + {"id", num++}, + {"address", doh->d_tlsContext.d_addr.toStringWithPort()}, + {"http-connects", (double)doh->d_httpconnects}, + {"http1-queries", (double)doh->d_http1Stats.d_nbQueries}, + {"http2-queries", (double)doh->d_http2Stats.d_nbQueries}, + {"http1-200-responses", (double)doh->d_http1Stats.d_nb200Responses}, + {"http2-200-responses", (double)doh->d_http2Stats.d_nb200Responses}, + {"http1-400-responses", (double)doh->d_http1Stats.d_nb400Responses}, + {"http2-400-responses", (double)doh->d_http2Stats.d_nb400Responses}, + {"http1-403-responses", (double)doh->d_http1Stats.d_nb403Responses}, + {"http2-403-responses", (double)doh->d_http2Stats.d_nb403Responses}, + {"http1-500-responses", (double)doh->d_http1Stats.d_nb500Responses}, + {"http2-500-responses", (double)doh->d_http2Stats.d_nb500Responses}, + {"http1-502-responses", (double)doh->d_http1Stats.d_nb502Responses}, + {"http2-502-responses", (double)doh->d_http2Stats.d_nb502Responses}, + {"http1-other-responses", (double)doh->d_http1Stats.d_nbOtherResponses}, + {"http2-other-responses", (double)doh->d_http2Stats.d_nbOtherResponses}, + {"get-queries", (double)doh->d_getqueries}, + {"post-queries", (double)doh->d_postqueries}, + {"bad-requests", (double)doh->d_badrequests}, + {"error-responses", (double)doh->d_errorresponses}, + {"redirect-responses", (double)doh->d_redirectresponses}, + {"valid-responses", (double)doh->d_validresponses}}); } } #endif /* HAVE_DNS_OVER_HTTPS */ @@ -1236,21 +1237,20 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) pools.reserve(localPools->size()); for (const auto& pool : *localPools) { const auto& cache = pool.second->packetCache; - Json::object entry { - { "id", num++ }, - { "name", pool.first }, - { "serversCount", (double) pool.second->countServers(false) }, - { "cacheSize", (double) (cache ? cache->getMaxEntries() : 0) }, - { "cacheEntries", (double) (cache ? cache->getEntriesCount() : 0) }, - { "cacheHits", (double) (cache ? cache->getHits() : 0) }, - { "cacheMisses", (double) (cache ? cache->getMisses() : 0) }, - { "cacheDeferredInserts", (double) (cache ? cache->getDeferredInserts() : 0) }, - { "cacheDeferredLookups", (double) (cache ? cache->getDeferredLookups() : 0) }, - { "cacheLookupCollisions", (double) (cache ? cache->getLookupCollisions() : 0) }, - { "cacheInsertCollisions", (double) (cache ? cache->getInsertCollisions() : 0) }, - { "cacheTTLTooShorts", (double) (cache ? cache->getTTLTooShorts() : 0) }, - { "cacheCleanupCount", (double) (cache ? cache->getCleanupCount() : 0) } - }; + Json::object entry{ + {"id", num++}, + {"name", pool.first}, + {"serversCount", (double)pool.second->countServers(false)}, + {"cacheSize", (double)(cache ? cache->getMaxEntries() : 0)}, + {"cacheEntries", (double)(cache ? cache->getEntriesCount() : 0)}, + {"cacheHits", (double)(cache ? cache->getHits() : 0)}, + {"cacheMisses", (double)(cache ? cache->getMisses() : 0)}, + {"cacheDeferredInserts", (double)(cache ? cache->getDeferredInserts() : 0)}, + {"cacheDeferredLookups", (double)(cache ? cache->getDeferredLookups() : 0)}, + {"cacheLookupCollisions", (double)(cache ? cache->getLookupCollisions() : 0)}, + {"cacheInsertCollisions", (double)(cache ? cache->getInsertCollisions() : 0)}, + {"cacheTTLTooShorts", (double)(cache ? cache->getTTLTooShorts() : 0)}, + {"cacheCleanupCount", (double)(cache ? cache->getCleanupCount() : 0)}}; pools.push_back(std::move(entry)); } } @@ -1271,8 +1271,7 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) {"matches", (double)a.d_rule->d_matches}, {"rule", a.d_rule->toString()}, {"action", a.d_action->toString()}, - {"action-stats", a.d_action->getStats()} - }; + {"action-stats", a.d_action->getStats()}}; rules.push_back(std::move(rule)); } } @@ -1310,22 +1309,20 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) Json::object stats; addStatsToJSONObject(stats); - Json responseObject(Json::object({ - { "daemon_type", "dnsdist" }, - { "version", VERSION }, - { "servers", std::move(servers) }, - { "frontends", std::move(frontends) }, - { "pools", std::move(pools) }, - { "rules", std::move(rules) }, - { "response-rules", std::move(responseRules) }, - { "cache-hit-response-rules", std::move(cacheHitResponseRules) }, - { "cache-inserted-response-rules", std::move(cacheInsertedResponseRules) }, - { "self-answered-response-rules", std::move(selfAnsweredResponseRules) }, - { "acl", std::move(acl) }, - { "local", std::move(localaddressesStr) }, - { "dohFrontends", std::move(dohs) }, - { "statistics", std::move(stats) } - })); + Json responseObject(Json::object({{"daemon_type", "dnsdist"}, + {"version", VERSION}, + {"servers", std::move(servers)}, + {"frontends", std::move(frontends)}, + {"pools", std::move(pools)}, + {"rules", std::move(rules)}, + {"response-rules", std::move(responseRules)}, + {"cache-hit-response-rules", std::move(cacheHitResponseRules)}, + {"cache-inserted-response-rules", std::move(cacheInsertedResponseRules)}, + {"self-answered-response-rules", std::move(selfAnsweredResponseRules)}, + {"acl", std::move(acl)}, + {"local", std::move(localaddressesStr)}, + {"dohFrontends", std::move(dohs)}, + {"statistics", std::move(stats)}})); resp.headers["Content-Type"] = "application/json"; resp.body = responseObject.dump(); @@ -1352,20 +1349,19 @@ static void handlePoolStats(const YaHTTP::Request& req, YaHTTP::Response& resp) const auto& pool = poolIt->second; const auto& cache = pool->packetCache; - Json::object entry { - { "name", poolName->second }, - { "serversCount", (double) pool->countServers(false) }, - { "cacheSize", (double) (cache ? cache->getMaxEntries() : 0) }, - { "cacheEntries", (double) (cache ? cache->getEntriesCount() : 0) }, - { "cacheHits", (double) (cache ? cache->getHits() : 0) }, - { "cacheMisses", (double) (cache ? cache->getMisses() : 0) }, - { "cacheDeferredInserts", (double) (cache ? cache->getDeferredInserts() : 0) }, - { "cacheDeferredLookups", (double) (cache ? cache->getDeferredLookups() : 0) }, - { "cacheLookupCollisions", (double) (cache ? cache->getLookupCollisions() : 0) }, - { "cacheInsertCollisions", (double) (cache ? cache->getInsertCollisions() : 0) }, - { "cacheTTLTooShorts", (double) (cache ? cache->getTTLTooShorts() : 0) }, - { "cacheCleanupCount", (double) (cache ? cache->getCleanupCount() : 0) } - }; + Json::object entry{ + {"name", poolName->second}, + {"serversCount", (double)pool->countServers(false)}, + {"cacheSize", (double)(cache ? cache->getMaxEntries() : 0)}, + {"cacheEntries", (double)(cache ? cache->getEntriesCount() : 0)}, + {"cacheHits", (double)(cache ? cache->getHits() : 0)}, + {"cacheMisses", (double)(cache ? cache->getMisses() : 0)}, + {"cacheDeferredInserts", (double)(cache ? cache->getDeferredInserts() : 0)}, + {"cacheDeferredLookups", (double)(cache ? cache->getDeferredLookups() : 0)}, + {"cacheLookupCollisions", (double)(cache ? cache->getLookupCollisions() : 0)}, + {"cacheInsertCollisions", (double)(cache ? cache->getInsertCollisions() : 0)}, + {"cacheTTLTooShorts", (double)(cache ? cache->getTTLTooShorts() : 0)}, + {"cacheCleanupCount", (double)(cache ? cache->getCleanupCount() : 0)}}; Json::array servers; int num = 0; @@ -1375,10 +1371,9 @@ static void handlePoolStats(const YaHTTP::Request& req, YaHTTP::Response& resp) } resp.headers["Content-Type"] = "application/json"; - Json my_json = Json::object { - { "stats", entry }, - { "servers", servers } - }; + Json my_json = Json::object{ + {"stats", entry}, + {"servers", servers}}; resp.body = my_json.dump(); } @@ -1397,32 +1392,28 @@ static void handleStatsOnly(const YaHTTP::Request& req, YaHTTP::Response& resp) } if (const auto& val = std::get_if(&item.d_value)) { - doc.push_back(Json::object { - { "type", "StatisticItem" }, - { "name", item.d_name }, - { "value", (double)(*val)->load() } - }); + doc.push_back(Json::object{ + {"type", "StatisticItem"}, + {"name", item.d_name}, + {"value", (double)(*val)->load()}}); } else if (const auto& adval = std::get_if*>(&item.d_value)) { - doc.push_back(Json::object { - { "type", "StatisticItem" }, - { "name", item.d_name }, - { "value", (*adval)->load() } - }); + doc.push_back(Json::object{ + {"type", "StatisticItem"}, + {"name", item.d_name}, + {"value", (*adval)->load()}}); } else if (const auto& dval = std::get_if(&item.d_value)) { - doc.push_back(Json::object { - { "type", "StatisticItem" }, - { "name", item.d_name }, - { "value", (**dval) } - }); + doc.push_back(Json::object{ + {"type", "StatisticItem"}, + {"name", item.d_name}, + {"value", (**dval)}}); } else if (const auto& func = std::get_if(&item.d_value)) { - doc.push_back(Json::object { - { "type", "StatisticItem" }, - { "name", item.d_name }, - { "value", (double)(*func)(item.d_name) } - }); + doc.push_back(Json::object{ + {"type", "StatisticItem"}, + {"name", item.d_name}, + {"value", (double)(*func)(item.d_name)}}); } } } @@ -1439,44 +1430,40 @@ static void handleConfigDump(const YaHTTP::Request& req, YaHTTP::Response& resp) Json::array doc; typedef boost::variant configentry_t; - std::vector > configEntries { - { "acl", g_ACL.getLocal()->toString() }, - { "allow-empty-response", g_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 }, - { "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 } - }; - for(const auto& item : configEntries) { + std::vector> configEntries{ + {"acl", g_ACL.getLocal()->toString()}, + {"allow-empty-response", g_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}, + {"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}}; + for (const auto& item : configEntries) { if (const auto& bval = boost::get(&item.second)) { - doc.push_back(Json::object { - { "type", "ConfigSetting" }, - { "name", item.first }, - { "value", *bval } - }); + doc.push_back(Json::object{ + {"type", "ConfigSetting"}, + {"name", item.first}, + {"value", *bval}}); } else if (const auto& sval = boost::get(&item.second)) { - doc.push_back(Json::object { - { "type", "ConfigSetting" }, - { "name", item.first }, - { "value", *sval } - }); + doc.push_back(Json::object{ + {"type", "ConfigSetting"}, + {"name", item.first}, + {"value", *sval}}); } else if (const auto& dval = boost::get(&item.second)) { - doc.push_back(Json::object { - { "type", "ConfigSetting" }, - { "name", item.first }, - { "value", *dval } - }); + doc.push_back(Json::object{ + {"type", "ConfigSetting"}, + {"name", item.first}, + {"value", *dval}}); } } Json my_json = doc; @@ -1503,7 +1490,8 @@ static void handleAllowFrom(const YaHTTP::Request& req, YaHTTP::Response& resp) for (const auto& value : aclList.array_items()) { try { nmg.addMask(value.string_value()); - } catch (NetmaskException &e) { + } + catch (NetmaskException& e) { resp.status = 400; break; } @@ -1527,10 +1515,9 @@ static void handleAllowFrom(const YaHTTP::Request& req, YaHTTP::Response& resp) auto aclEntries = g_ACL.getLocal()->toStringVector(); Json::object obj{ - { "type", "ConfigSetting" }, - { "name", "allow-from" }, - { "value", aclEntries } - }; + {"type", "ConfigSetting"}, + {"name", "allow-from"}, + {"value", aclEntries}}; Json my_json = obj; resp.body = my_json.dump(); } @@ -1548,9 +1535,8 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& if (req.method != "DELETE") { resp.status = 400; Json::object obj{ - { "status", "denied" }, - { "error", "invalid method" } - }; + {"status", "denied"}, + {"error", "invalid method"}}; resp.body = Json(obj).dump(); return; } @@ -1562,8 +1548,8 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& if (poolName == req.getvars.end() || expungeName == req.getvars.end()) { resp.status = 400; Json::object obj{ - { "status", "denied" }, - { "error", "missing 'pool' or 'name' parameter" }, + {"status", "denied"}, + {"error", "missing 'pool' or 'name' parameter"}, }; resp.body = Json(obj).dump(); return; @@ -1577,8 +1563,8 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& catch (const std::exception& e) { resp.status = 400; Json::object obj{ - { "status", "error" }, - { "error", "unable to parse the requested name" }, + {"status", "error"}, + {"error", "unable to parse the requested name"}, }; resp.body = Json(obj).dump(); return; @@ -1594,8 +1580,8 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& catch (const std::exception& e) { resp.status = 404; Json::object obj{ - { "status", "not found" }, - { "error", "the requested pool does not exist" }, + {"status", "not found"}, + {"error", "the requested pool does not exist"}, }; resp.body = Json(obj).dump(); return; @@ -1605,8 +1591,8 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& if (cache == nullptr) { resp.status = 404; Json::object obj{ - { "status", "not found" }, - { "error", "there is no cache associated with the requested pool" }, + {"status", "not found"}, + {"error", "there is no cache associated with the requested pool"}, }; resp.body = Json(obj).dump(); return; @@ -1615,25 +1601,25 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& auto removed = cache->expungeByName(name, type.getCode(), suffix != req.getvars.end()); Json::object obj{ - { "status", "purged" }, - { "count", std::to_string(removed) } - }; + {"status", "purged"}, + {"count", std::to_string(removed)}}; resp.body = Json(obj).dump(); } #endif /* DISABLE_WEB_CACHE_MANAGEMENT */ -template static void addRingEntryToList(const struct timespec& now, Json::array& list, const T& entry) +template +static void addRingEntryToList(const struct timespec& now, Json::array& list, const T& entry) { constexpr bool response = std::is_same_v; Json::object tmp{ - { "age", static_cast(DiffTime(entry.when, now)) }, - { "id", ntohs(entry.dh.id) }, - { "name", entry.name.toString() }, - { "requestor", entry.requestor.toStringWithPort() }, - { "size", static_cast(entry.size) }, - { "qtype", entry.qtype }, - { "protocol", entry.protocol.toString() }, - { "rd", static_cast(entry.dh.rd) }, + {"age", static_cast(DiffTime(entry.when, now))}, + {"id", ntohs(entry.dh.id)}, + {"name", entry.name.toString()}, + {"requestor", entry.requestor.toStringWithPort()}, + {"size", static_cast(entry.size)}, + {"qtype", entry.qtype}, + {"protocol", entry.protocol.toString()}, + {"rd", static_cast(entry.dh.rd)}, }; if constexpr (!response) { #if defined(DNSDIST_RINGS_WITH_MACADDRESS) @@ -1747,20 +1733,20 @@ static void redirectToIndex(const YaHTTP::Request& req, YaHTTP::Response& resp) static void handleBuiltInFiles(const YaHTTP::Request& req, YaHTTP::Response& resp) { - if (req.url.path.empty() || !s_urlmap.count(req.url.path.c_str()+1)) { + if (req.url.path.empty() || !s_urlmap.count(req.url.path.c_str() + 1)) { resp.status = 404; return; } - resp.body.assign(s_urlmap.at(req.url.path.c_str()+1)); + resp.body.assign(s_urlmap.at(req.url.path.c_str() + 1)); vector parts; stringtok(parts, req.url.path, "."); static const std::unordered_map contentTypeMap = { - { "html", "text/html" }, - { "css", "text/css" }, - { "js", "application/javascript" }, - { "png", "image/png" }, + {"html", "text/html"}, + {"css", "text/css"}, + {"js", "application/javascript"}, + {"png", "image/png"}, }; const auto& it = contentTypeMap.find(parts.back()); @@ -1820,7 +1806,8 @@ static void connectionThread(WebClientConnection&& conn) if (bytes > 0) { string data = string(buf, bytes); finished = yarl.feed(data); - } else { + } + else { // read error OR EOF break; } @@ -1893,7 +1880,8 @@ void setWebserverAPIKey(std::unique_ptr&& apiKey) if (apiKey) { config->apiKey = std::move(apiKey); - } else { + } + else { config->apiKey.reset(); } } @@ -1911,7 +1899,7 @@ void setWebserverACL(const std::string& acl) g_webserverConfig.lock()->acl = std::move(newACL); } -void setWebserverCustomHeaders(const boost::optional > customHeaders) +void setWebserverCustomHeaders(const boost::optional> customHeaders) { g_webserverConfig.lock()->customHeaders = customHeaders; } diff --git a/pdns/dnsdistdist/dnsdist-xpf.cc b/pdns/dnsdistdist/dnsdist-xpf.cc index eb2ba57855..305bf0433e 100644 --- a/pdns/dnsdistdist/dnsdist-xpf.cc +++ b/pdns/dnsdistdist/dnsdist-xpf.cc @@ -53,7 +53,7 @@ bool addXPF(DNSQuestion& dq, uint16_t optionCode) pos += sizeof(drh); memcpy(reinterpret_cast(&data.at(pos)), payload.data(), payload.size()); pos += payload.size(); - (void) pos; + (void)pos; dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) { header.arcount = htons(ntohs(header.arcount) + 1); diff --git a/pdns/dnsdistdist/dnsdist-xpf.hh b/pdns/dnsdistdist/dnsdist-xpf.hh index 2e66f65588..30de2234c0 100644 --- a/pdns/dnsdistdist/dnsdist-xpf.hh +++ b/pdns/dnsdistdist/dnsdist-xpf.hh @@ -24,4 +24,3 @@ #include "dnsdist.hh" bool addXPF(DNSQuestion& dq, uint16_t optionCode); - diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 6f0d4080ab..97f834ffd9 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -34,7 +34,7 @@ #include #ifdef HAVE_LIBEDIT -#if defined (__OpenBSD__) || defined(__NetBSD__) +#if defined(__OpenBSD__) || defined(__NetBSD__) // If this is not undeffed, __attribute__ wil be redefined by /usr/include/readline/rlstdc.h #undef __STRICT_ANSI__ #include @@ -117,7 +117,7 @@ std::vector> g_doh3locals; std::vector> g_dnsCryptLocals; shared_ptr g_defaultBPFFilter{nullptr}; -std::vector > g_dynBPFFilters; +std::vector> g_dynBPFFilters; std::vector> g_frontends; GlobalStateHolder g_pools; @@ -138,11 +138,11 @@ std::vector g_TCPFastOpenKey; IDs are assigned by atomic increments of the socket offset. */ -GlobalStateHolder > g_ruleactions; -GlobalStateHolder > g_respruleactions; -GlobalStateHolder > g_cachehitrespruleactions; -GlobalStateHolder > g_cacheInsertedRespRuleActions; -GlobalStateHolder > g_selfansweredrespruleactions; +GlobalStateHolder> g_ruleactions; +GlobalStateHolder> g_respruleactions; +GlobalStateHolder> g_cachehitrespruleactions; +GlobalStateHolder> g_cacheInsertedRespRuleActions; +GlobalStateHolder> g_selfansweredrespruleactions; Rings g_rings; QueryCount g_qcount; @@ -185,15 +185,14 @@ static ssize_t sendfromto(int sock, const void* data, size_t len, int flags, con addCMsgSrcAddr(&msgh, &cbuf, &from, 0); } else { - msgh.msg_control=nullptr; + msgh.msg_control = nullptr; } return sendmsg(sock, &msgh, flags); } static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qnameWireLength) { - try - { + try { bool hadEDNS = false; uint16_t payloadSize = 0; uint16_t z = 0; @@ -202,7 +201,7 @@ static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qn hadEDNS = getEDNSUDPPayloadSizeAndZ(reinterpret_cast(packet.data()), packet.size(), &payloadSize, &z); } - packet.resize(static_cast(sizeof(dnsheader)+qnameWireLength+DNS_TYPE_SIZE+DNS_CLASS_SIZE)); + packet.resize(static_cast(sizeof(dnsheader) + qnameWireLength + DNS_TYPE_SIZE + DNS_CLASS_SIZE)); dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [](dnsheader& header) { header.ancount = 0; header.arcount = 0; @@ -214,8 +213,7 @@ static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qn addEDNS(packet, maximumSize, z & EDNS_HEADER_FLAG_DO, payloadSize, 0); } } - catch(...) - { + catch (...) { ++dnsdist::metrics::g_stats.truncFail; } } @@ -273,7 +271,7 @@ bool DNSQuestion::editHeader(const std::function& editFunction static void doLatencyStats(dnsdist::Protocol protocol, double udiff) { constexpr auto doAvg = [](double& var, double n, double weight) { - var = (weight -1) * var/weight + n/weight; + var = (weight - 1) * var / weight + n / weight; }; if (protocol == dnsdist::Protocol::DoUDP || protocol == dnsdist::Protocol::DNSCryptUDP) { @@ -299,39 +297,39 @@ static void doLatencyStats(dnsdist::Protocol protocol, double udiff) dnsdist::metrics::g_stats.latencySum += udiff / 1000; ++dnsdist::metrics::g_stats.latencyCount; - doAvg(dnsdist::metrics::g_stats.latencyAvg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyAvg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyAvg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyAvg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyAvg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyAvg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyAvg1000000, udiff, 1000000); } else if (protocol == dnsdist::Protocol::DoTCP || protocol == dnsdist::Protocol::DNSCryptTCP) { - doAvg(dnsdist::metrics::g_stats.latencyTCPAvg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyTCPAvg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyTCPAvg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyTCPAvg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyTCPAvg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyTCPAvg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyTCPAvg1000000, udiff, 1000000); } else if (protocol == dnsdist::Protocol::DoT) { - doAvg(dnsdist::metrics::g_stats.latencyDoTAvg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyDoTAvg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyDoTAvg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyDoTAvg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyDoTAvg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyDoTAvg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyDoTAvg1000000, udiff, 1000000); } else if (protocol == dnsdist::Protocol::DoH) { - doAvg(dnsdist::metrics::g_stats.latencyDoHAvg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyDoHAvg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyDoHAvg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyDoHAvg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyDoHAvg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyDoHAvg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyDoHAvg1000000, udiff, 1000000); } else if (protocol == dnsdist::Protocol::DoQ) { - doAvg(dnsdist::metrics::g_stats.latencyDoQAvg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyDoQAvg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyDoQAvg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyDoQAvg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyDoQAvg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyDoQAvg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyDoQAvg1000000, udiff, 1000000); } else if (protocol == dnsdist::Protocol::DoH3) { - doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg100, udiff, 100); - doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg1000, udiff, 1000); - doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg10000, udiff, 10000); + doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg100, udiff, 100); + doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg1000, udiff, 1000); + doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg10000, udiff, 10000); doAvg(dnsdist::metrics::g_stats.latencyDoH3Avg1000000, udiff, 1000000); } } @@ -814,107 +812,106 @@ bool processResponderPacket(std::shared_ptr& dss, PacketBuffer& void responderThread(std::shared_ptr dss) { try { - setThreadName("dnsdist/respond"); - auto localRespRuleActions = g_respruleactions.getLocal(); - auto localCacheInsertedRespRuleActions = g_cacheInsertedRespRuleActions.getLocal(); - const size_t initialBufferSize = getInitialUDPPacketBufferSize(false); - /* allocate one more byte so we can detect truncation */ - PacketBuffer response(initialBufferSize + 1); - uint16_t queryId = 0; - std::vector sockets; - sockets.reserve(dss->sockets.size()); - - for (;;) { - try { - if (dss->isStopped()) { - break; - } - - if (!dss->connected) { - /* the sockets are not connected yet, likely because we detected a problem, - tried to reconnect and it failed. We will try to reconnect after the next - successful health-check (unless reconnectOnUp is false), or when trying - to send in the UDP listener thread, but until then we simply need to wait. */ - dss->waitUntilConnected(); - continue; - } - - dss->pickSocketsReadyForReceiving(sockets); - - /* check a second time here because we might have waited quite a bit - since the first check */ - if (dss->isStopped()) { - break; - } - - for (const auto& fd : sockets) { - /* allocate one more byte so we can detect truncation */ - // NOLINTNEXTLINE(bugprone-use-after-move): resizing a vector has no preconditions so it is valid to do so after moving it - response.resize(initialBufferSize + 1); - ssize_t got = recv(fd, response.data(), response.size(), 0); - - if (got == 0 && dss->isStopped()) { + setThreadName("dnsdist/respond"); + auto localRespRuleActions = g_respruleactions.getLocal(); + auto localCacheInsertedRespRuleActions = g_cacheInsertedRespRuleActions.getLocal(); + const size_t initialBufferSize = getInitialUDPPacketBufferSize(false); + /* allocate one more byte so we can detect truncation */ + PacketBuffer response(initialBufferSize + 1); + uint16_t queryId = 0; + std::vector sockets; + sockets.reserve(dss->sockets.size()); + + for (;;) { + try { + if (dss->isStopped()) { break; } - if (got < 0 || static_cast(got) < sizeof(dnsheader) || static_cast(got) == (initialBufferSize + 1)) { + if (!dss->connected) { + /* the sockets are not connected yet, likely because we detected a problem, + tried to reconnect and it failed. We will try to reconnect after the next + successful health-check (unless reconnectOnUp is false), or when trying + to send in the UDP listener thread, but until then we simply need to wait. */ + dss->waitUntilConnected(); continue; } - response.resize(static_cast(got)); - const dnsheader_aligned dnsHeader(response.data()); - queryId = dnsHeader->id; + dss->pickSocketsReadyForReceiving(sockets); - auto ids = dss->getState(queryId); - if (!ids) { - continue; + /* check a second time here because we might have waited quite a bit + since the first check */ + if (dss->isStopped()) { + break; } - if (!ids->isXSK() && fd != ids->backendFD) { - dss->restoreState(queryId, std::move(*ids)); - continue; - } + for (const auto& fd : sockets) { + /* allocate one more byte so we can detect truncation */ + // NOLINTNEXTLINE(bugprone-use-after-move): resizing a vector has no preconditions so it is valid to do so after moving it + response.resize(initialBufferSize + 1); + ssize_t got = recv(fd, response.data(), response.size(), 0); - if (processResponderPacket(dss, response, *localRespRuleActions, *localCacheInsertedRespRuleActions, std::move(*ids)) && ids->isXSK() && ids->cs->xskInfo) { -#ifdef HAVE_XSK - auto& xskInfo = ids->cs->xskInfo; - auto xskPacket = xskInfo->getEmptyFrame(); - if (!xskPacket) { + if (got == 0 && dss->isStopped()) { + break; + } + + if (got < 0 || static_cast(got) < sizeof(dnsheader) || static_cast(got) == (initialBufferSize + 1)) { + continue; + } + + response.resize(static_cast(got)); + const dnsheader_aligned dnsHeader(response.data()); + queryId = dnsHeader->id; + + auto ids = dss->getState(queryId); + if (!ids) { continue; } - xskPacket->setHeader(ids->xskPacketHeader); - if (!xskPacket->setPayload(response)) { - } - if (ids->delayMsec > 0) { - xskPacket->addDelay(ids->delayMsec); + + if (!ids->isXSK() && fd != ids->backendFD) { + dss->restoreState(queryId, std::move(*ids)); + continue; } - xskPacket->updatePacket(); - xskInfo->pushToSendQueue(*xskPacket); - xskInfo->notifyXskSocket(); + + if (processResponderPacket(dss, response, *localRespRuleActions, *localCacheInsertedRespRuleActions, std::move(*ids)) && ids->isXSK() && ids->cs->xskInfo) { +#ifdef HAVE_XSK + auto& xskInfo = ids->cs->xskInfo; + auto xskPacket = xskInfo->getEmptyFrame(); + if (!xskPacket) { + continue; + } + xskPacket->setHeader(ids->xskPacketHeader); + if (!xskPacket->setPayload(response)) { + } + if (ids->delayMsec > 0) { + xskPacket->addDelay(ids->delayMsec); + } + xskPacket->updatePacket(); + xskInfo->pushToSendQueue(*xskPacket); + xskInfo->notifyXskSocket(); #endif /* HAVE_XSK */ + } } } - } - catch (const std::exception& e) { - vinfolog("Got an error in UDP responder thread while parsing a response from %s, id %d: %s", dss->d_config.remote.toStringWithPort(), queryId, e.what()); + catch (const std::exception& e) { + vinfolog("Got an error in UDP responder thread while parsing a response from %s, id %d: %s", dss->d_config.remote.toStringWithPort(), queryId, e.what()); + } } } -} -catch (const std::exception& e) { - errlog("UDP responder thread died because of exception: %s", e.what()); -} -catch (const PDNSException& e) { - errlog("UDP responder thread died because of PowerDNS exception: %s", e.reason); -} -catch (...) { - errlog("UDP responder thread died because of an exception: %s", "unknown"); -} + catch (const std::exception& e) { + errlog("UDP responder thread died because of exception: %s", e.what()); + } + catch (const PDNSException& e) { + errlog("UDP responder thread died because of PowerDNS exception: %s", e.reason); + } + catch (...) { + errlog("UDP responder thread died because of an exception: %s", "unknown"); + } } LockGuarded g_lua{LuaContext()}; ComboAddress g_serverControl{"127.0.0.1:5199"}; - static void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent, bool raw) { string result; @@ -935,12 +932,13 @@ static void spoofResponseFromString(DNSQuestion& dq, const string& spoofContent, SpoofAction tempSpoofAction({spoofAddr}); tempSpoofAction(&dq, &result); } - catch(const PDNSException &e) { + catch (const PDNSException& e) { DNSName cname(spoofContent); SpoofAction tempSpoofAction(cname); // CNAME then tempSpoofAction(&dq, &result); } - } else { + } + else { std::vector cas; for (const auto& addr : addrs) { try { @@ -1054,7 +1052,6 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s return false; } - static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const struct timespec& now) { if (g_rings.shouldRecordQueries()) { @@ -1066,7 +1063,7 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru bool countQuery{true}; if (g_qcount.filter) { auto lock = g_lua.lock(); - std::tie (countQuery, qname) = g_qcount.filter(&dq); + std::tie(countQuery, qname) = g_qcount.filter(&dq); } if (countQuery) { @@ -1248,7 +1245,7 @@ ssize_t udpClientSendRequestToBackend(const std::shared_ptr& ss struct iovec iov; cmsgbuf_aligned cbuf; ComboAddress remote(ss->d_config.remote); - fillMSGHdr(&msgh, &iov, &cbuf, sizeof(cbuf), const_cast(reinterpret_cast(request.data())), request.size(), &remote); + fillMSGHdr(&msgh, &iov, &cbuf, sizeof(cbuf), const_cast(reinterpret_cast(request.data())), request.size(), &remote); addCMsgSrcAddr(&msgh, &cbuf, &ss->d_config.sourceAddr, ss->d_config.sourceItf); result = sendmsg(sd, &msgh, 0); } @@ -1341,7 +1338,7 @@ bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::unique_ bool checkQueryHeaders(const struct dnsheader& dnsHeader, ClientState& clientState) { - if (dnsHeader.qr) { // don't respond to responses + if (dnsHeader.qr) { // don't respond to responses ++dnsdist::metrics::g_stats.nonCompliantQueries; ++clientState.nonCompliantQueries; return false; @@ -1366,7 +1363,7 @@ bool checkQueryHeaders(const struct dnsheader& dnsHeader, ClientState& clientSta static void queueResponse(const ClientState& cs, const PacketBuffer& response, const ComboAddress& dest, const ComboAddress& remote, struct mmsghdr& outMsg, struct iovec* iov, cmsgbuf_aligned* cbuf) { outMsg.msg_len = 0; - fillMSGHdr(&outMsg.msg_hdr, iov, nullptr, 0, const_cast(reinterpret_cast(&response.at(0))), response.size(), const_cast(&remote)); + fillMSGHdr(&outMsg.msg_hdr, iov, nullptr, 0, const_cast(reinterpret_cast(&response.at(0))), response.size(), const_cast(&remote)); if (dest.sin4.sin_family == 0) { outMsg.msg_hdr.msg_control = nullptr; @@ -1499,7 +1496,7 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders yet, as we will do a second-lookup */ if (dq.ids.packetCache->get(dq, dq.getHeader()->id, &dq.ids.cacheKey, dq.ids.subnet, dq.ids.dnssecOK, forwardedOverUDP, allowExpired, false, true, dq.ids.protocol != dnsdist::Protocol::DoH || forwardedOverUDP)) { - dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [flags=dq.ids.origFlags](dnsheader& header) { + dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [flags = dq.ids.origFlags](dnsheader& header) { restoreFlags(&header, flags); return true; }); @@ -1574,7 +1571,7 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders selectedBackend->incQueriesCount(); return ProcessQueryResult::PassToBackend; } - catch (const std::exception& e){ + catch (const std::exception& e) { vinfolog("Got an error while parsing a %s query (after applying rules) from %s, id %d: %s", (dq.overTCP() ? "TCP" : "UDP"), dq.ids.origRemote.toStringWithPort(), queryId, e.what()); } return ProcessQueryResult::Drop; @@ -1624,7 +1621,8 @@ public: class UDPCrossProtocolQuery : public CrossProtocolQuery { public: - UDPCrossProtocolQuery(PacketBuffer&& buffer_, InternalQueryState&& ids_, std::shared_ptr ds): CrossProtocolQuery(InternalQuery(std::move(buffer_), std::move(ids_)), ds) + UDPCrossProtocolQuery(PacketBuffer&& buffer_, InternalQueryState&& ids_, std::shared_ptr ds) : + CrossProtocolQuery(InternalQuery(std::move(buffer_), std::move(ids_)), ds) { auto& ids = query.d_idstate; const auto& buffer = query.d_buffer; @@ -1646,6 +1644,7 @@ public: { return s_sender; } + private: static std::shared_ptr s_sender; }; @@ -1680,7 +1679,7 @@ ProcessQueryResult processQuery(DNSQuestion& dq, LocalHolders& holders, std::sha return processQueryAfterRules(dq, holders, selectedBackend); } - catch (const std::exception& e){ + catch (const std::exception& e) { vinfolog("Got an error while parsing a %s query from %s, id %d: %s", (dq.overTCP() ? "TCP" : "UDP"), dq.ids.origRemote.toStringWithPort(), queryId, e.what()); } return ProcessQueryResult::Drop; @@ -1877,7 +1876,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct assignOutgoingUDPQueryToBackend(ss, dh->id, dq, query); } - catch(const std::exception& e){ + catch (const std::exception& e) { vinfolog("Got an error in UDP question thread while parsing a query from %s, id %d: %s", ids.origRemote.toStringWithPort(), queryId, e.what()); } } @@ -2050,7 +2049,7 @@ static void MultipleMessagesUDPClientThread(ClientState* cs, LocalHolders& holde } /* go now */ - for(;;) { + for (;;) { /* reset the IO vector, since it's also used to send the vector of responses to avoid having to copy the data around */ @@ -2097,7 +2096,6 @@ static void MultipleMessagesUDPClientThread(ClientState* cs, LocalHolders& holde vinfolog("Error sending responses with sendmmsg() (%d on %u): %s", sent, msgsToSend, stringerror()); } } - } } #endif /* defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE) */ @@ -2210,10 +2208,10 @@ static void udpClientThread(std::vector states) } } } - catch (const std::exception &e) { + catch (const std::exception& e) { errlog("UDP client thread died because of exception: %s", e.what()); } - catch (const PDNSException &e) { + catch (const PDNSException& e) { errlog("UDP client thread died because of PowerDNS exception: %s", e.reason); } catch (...) { @@ -2238,14 +2236,14 @@ static void maintThread() { auto lua = g_lua.lock(); try { - auto maintenanceCallback = lua->readVariable > >("maintenance"); + auto maintenanceCallback = lua->readVariable>>("maintenance"); if (maintenanceCallback) { (*maintenanceCallback)(); } dnsdist::lua::hooks::runMaintenanceHooks(*lua); secondsToWaitLog = 0; } - catch (const std::exception &e) { + catch (const std::exception& e) { if (secondsToWaitLog <= 0) { warnlog("Error during execution of maintenance function(s): %s", e.what()); secondsToWaitLog = 61; @@ -2291,7 +2289,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 - g_cacheCleaningPercentage)) / 100; packetCache->purgeExpired(upTo, now); } counter = 0; @@ -2317,7 +2315,7 @@ static void secPollThread() try { doSecPoll(g_secPollSuffix); } - catch(...) { + catch (...) { } // coverity[store_truncates_time_t] sleep(g_secPollInterval); @@ -2330,7 +2328,8 @@ static void healthChecksThread() setThreadName("dnsdist/healthC"); constexpr int intervalUsec = 1000 * 1000; - struct timeval lastRound{ + struct timeval lastRound + { .tv_sec = 0, .tv_usec = 0 }; @@ -2475,7 +2474,7 @@ static bool g_warned_ipv6_recvpktinfo = false; static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, int& socket, bool tcp, bool warn) { - (void) warn; + (void)warn; socket = SSocket(addr.sin4.sin_family, !tcp ? SOCK_DGRAM : SOCK_STREAM, 0); if (tcp) { @@ -2510,10 +2509,9 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, if (!tcp && IsAnyAddress(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 + (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 && !g_warned_ipv6_recvpktinfo) { warnlog("Warning: IPV6_RECVPKTINFO setsockopt failed: %s", stringerror()); g_warned_ipv6_recvpktinfo = true; } @@ -2559,13 +2557,15 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, catch (const std::exception& e) { warnlog(e.what()); } - } else { + } + else { try { auto result = raiseSocketSendBufferToMax(socket); if (result > 0) { infolog("Raised send buffer to %u for local address '%s'", result, addr.toStringWithPort()); } - } catch (const std::exception& e) { + } + catch (const std::exception& e) { warnlog(e.what()); } } @@ -2577,13 +2577,15 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, catch (const std::exception& e) { warnlog(e.what()); } - } else { + } + else { try { auto result = raiseSocketReceiveBufferToMax(socket); if (result > 0) { infolog("Raised receive buffer to %u for local address '%s'", result, addr.toStringWithPort()); } - } catch (const std::exception& e) { + } + catch (const std::exception& e) { warnlog(e.what()); } } @@ -2627,10 +2629,12 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, else { infolog("Listening on %s", addr.toStringWithPort()); } - } else { + } + else { if (clientState.doqFrontend != nullptr) { infolog("Listening on %s for DoQ", addr.toStringWithPort()); - } else if (clientState.doh3Frontend != nullptr) { + } + else if (clientState.doh3Frontend != nullptr) { infolog("Listening on %s for DoH3", addr.toStringWithPort()); } #ifdef HAVE_XSK @@ -2646,7 +2650,7 @@ static void setUpLocalBind(std::unique_ptr& cstate) /* skip some warnings if there is an identical UDP context */ bool warn = !cstate->tcp || cstate->tlsFrontend != nullptr || cstate->dohFrontend != nullptr; int& descriptor = !cstate->tcp ? cstate->udpFD : cstate->tcpFD; - (void) warn; + (void)warn; setupLocalSocket(*cstate, cstate->local, descriptor, cstate->tcp, warn); @@ -2691,37 +2695,37 @@ std::atomic g_configurationDone{false}; static void usage() { - cout< longopts{{ - {"acl", required_argument, nullptr, 'a'}, - {"check-config", no_argument, nullptr, 1}, - {"client", no_argument, nullptr, 'c'}, - {"config", required_argument, nullptr, 'C'}, - {"disable-syslog", no_argument, nullptr, 2}, - {"execute", required_argument, nullptr, 'e'}, - {"gid", required_argument, nullptr, 'g'}, - {"help", no_argument, nullptr, 'h'}, - {"local", required_argument, nullptr, 'l'}, - {"log-timestamps", no_argument, nullptr, 4}, - {"setkey", required_argument, nullptr, 'k'}, - {"supervised", no_argument, nullptr, 3}, - {"uid", required_argument, nullptr, 'u'}, - {"verbose", no_argument, nullptr, 'v'}, - {"version", no_argument, nullptr, 'V'}, - {nullptr, 0, nullptr, 0} - }}; + const std::array longopts{{{"acl", required_argument, nullptr, 'a'}, + {"check-config", no_argument, nullptr, 1}, + {"client", no_argument, nullptr, 'c'}, + {"config", required_argument, nullptr, 'C'}, + {"disable-syslog", no_argument, nullptr, 2}, + {"execute", required_argument, nullptr, 'e'}, + {"gid", required_argument, nullptr, 'g'}, + {"help", no_argument, nullptr, 'h'}, + {"local", required_argument, nullptr, 'l'}, + {"log-timestamps", no_argument, nullptr, 4}, + {"setkey", required_argument, nullptr, 'k'}, + {"supervised", no_argument, nullptr, 3}, + {"uid", required_argument, nullptr, 'u'}, + {"verbose", no_argument, nullptr, 'v'}, + {"version", no_argument, nullptr, 'V'}, + {nullptr, 0, nullptr, 0}}}; int longindex = 0; string optstring; while (true) { @@ -2917,9 +2919,9 @@ static void parseParameters(int argc, char** argv, ComboAddress& clientAddress) g_cmdLine.gid = optarg; break; case 'h': - cout<<"dnsdist "<getName() == "chashed") { precompute = true; - } else { - for (const auto& entry: pools) { + } + else { + for (const auto& entry : pools) { if (entry.second->policy != nullptr && entry.second->policy->getName() == "chashed") { precompute = true; - break ; + break; } } } @@ -2994,7 +2998,7 @@ static void setupPools() vinfolog("Pre-computing hashes for consistent hash load-balancing policy"); // pre compute hashes auto backends = g_dstates.getLocal(); - for (const auto& backend: *backends) { + for (const auto& backend : *backends) { if (backend->d_config.d_weight < 100) { vinfolog("Warning, the backend '%s' has a very low weight (%d), which will not yield a good distribution of queries with the 'chashed' policy. Please consider raising it to at least '100'.", backend->getName(), backend->d_config.d_weight); } @@ -3019,8 +3023,7 @@ static void dropPrivileges() } bool retainedCapabilities = true; - if (!g_capabilitiesToRetain.empty() && - (getegid() != newgid || geteuid() != newuid)) { + if (!g_capabilitiesToRetain.empty() && (getegid() != newgid || geteuid() != newuid)) { retainedCapabilities = keepCapabilitiesAfterSwitchingIDs(); } @@ -3061,7 +3064,7 @@ static void dropPrivileges() static void initFrontends() { if (!g_cmdLine.locals.empty()) { - for (auto it = g_frontends.begin(); it != g_frontends.end(); ) { + for (auto it = g_frontends.begin(); it != g_frontends.end();) { /* DoH, DoT and DNSCrypt frontends are separate */ if ((*it)->dohFrontend == nullptr && (*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr && (*it)->doqFrontend == nullptr && (*it)->doh3Frontend == nullptr) { it = g_frontends.erase(it); @@ -3081,9 +3084,9 @@ static void initFrontends() if (g_frontends.empty()) { /* UDP */ - g_frontends.emplace_back(std::make_unique(ComboAddress("127.0.0.1", 53), false, false, 0, "", std::set{}, true)); + g_frontends.emplace_back(std::make_unique(ComboAddress("127.0.0.1", 53), false, false, 0, "", std::set{}, true)); /* TCP */ - g_frontends.emplace_back(std::make_unique(ComboAddress("127.0.0.1", 53), true, false, 0, "", std::set{}, true)); + g_frontends.emplace_back(std::make_unique(ComboAddress("127.0.0.1", 53), true, false, 0, "", std::set{}, true)); } } @@ -3123,59 +3126,59 @@ static void startFrontends() dotThreadHandle.detach(); #endif /* HAVE_LIBH2OEVLOOP */ #endif /* HAVE_DNS_OVER_HTTPS */ - continue; - } - if (clientState->doqFrontend != nullptr) { + continue; + } + if (clientState->doqFrontend != nullptr) { #ifdef HAVE_DNS_OVER_QUIC - std::thread doqThreadHandle(doqThread, clientState.get()); - if (!clientState->cpus.empty()) { - mapThreadToCPUList(doqThreadHandle.native_handle(), clientState->cpus); - } - doqThreadHandle.detach(); -#endif /* HAVE_DNS_OVER_QUIC */ - continue; + std::thread doqThreadHandle(doqThread, clientState.get()); + if (!clientState->cpus.empty()) { + mapThreadToCPUList(doqThreadHandle.native_handle(), clientState->cpus); } - if (clientState->doh3Frontend != nullptr) { + doqThreadHandle.detach(); +#endif /* HAVE_DNS_OVER_QUIC */ + continue; + } + if (clientState->doh3Frontend != nullptr) { #ifdef HAVE_DNS_OVER_HTTP3 - std::thread doh3ThreadHandle(doh3Thread, clientState.get()); - if (!clientState->cpus.empty()) { - mapThreadToCPUList(doh3ThreadHandle.native_handle(), clientState->cpus); - } - doh3ThreadHandle.detach(); -#endif /* HAVE_DNS_OVER_HTTP3 */ - continue; + std::thread doh3ThreadHandle(doh3Thread, clientState.get()); + if (!clientState->cpus.empty()) { + mapThreadToCPUList(doh3ThreadHandle.native_handle(), clientState->cpus); } - if (clientState->udpFD >= 0) { + doh3ThreadHandle.detach(); +#endif /* HAVE_DNS_OVER_HTTP3 */ + continue; + } + if (clientState->udpFD >= 0) { #ifdef USE_SINGLE_ACCEPTOR_THREAD - udpStates.push_back(clientState.get()); + udpStates.push_back(clientState.get()); #else /* USE_SINGLE_ACCEPTOR_THREAD */ - std::thread udpClientThreadHandle(udpClientThread, std::vector{ clientState.get() }); - if (!clientState->cpus.empty()) { - mapThreadToCPUList(udpClientThreadHandle.native_handle(), clientState->cpus); - } - udpClientThreadHandle.detach(); -#endif /* USE_SINGLE_ACCEPTOR_THREAD */ + std::thread udpClientThreadHandle(udpClientThread, std::vector{clientState.get()}); + if (!clientState->cpus.empty()) { + mapThreadToCPUList(udpClientThreadHandle.native_handle(), clientState->cpus); } - else if (clientState->tcpFD >= 0) { + udpClientThreadHandle.detach(); +#endif /* USE_SINGLE_ACCEPTOR_THREAD */ + } + else if (clientState->tcpFD >= 0) { #ifdef USE_SINGLE_ACCEPTOR_THREAD - tcpStates.push_back(clientState.get()); + tcpStates.push_back(clientState.get()); #else /* USE_SINGLE_ACCEPTOR_THREAD */ - std::thread tcpAcceptorThreadHandle(tcpAcceptorThread, std::vector{clientState.get() }); - if (!clientState->cpus.empty()) { - mapThreadToCPUList(tcpAcceptorThreadHandle.native_handle(), clientState->cpus); - } - tcpAcceptorThreadHandle.detach(); -#endif /* USE_SINGLE_ACCEPTOR_THREAD */ + std::thread tcpAcceptorThreadHandle(tcpAcceptorThread, std::vector{clientState.get()}); + if (!clientState->cpus.empty()) { + mapThreadToCPUList(tcpAcceptorThreadHandle.native_handle(), clientState->cpus); } + tcpAcceptorThreadHandle.detach(); +#endif /* USE_SINGLE_ACCEPTOR_THREAD */ } + } #ifdef USE_SINGLE_ACCEPTOR_THREAD - if (!udpStates.empty()) { - std::thread udpThreadHandle(udpClientThread, udpStates); - udpThreadHandle.detach(); - } - if (!tcpStates.empty()) { - g_tcpclientthreads = std::make_unique(1, tcpStates); - } + if (!udpStates.empty()) { + std::thread udpThreadHandle(udpClientThread, udpStates); + udpThreadHandle.detach(); + } + if (!tcpStates.empty()) { + g_tcpclientthreads = std::make_unique(1, tcpStates); + } #endif /* USE_SINGLE_ACCEPTOR_THREAD */ } } @@ -3198,11 +3201,11 @@ int main(int argc, char** argv) signal(SIGCHLD, SIG_IGN); signal(SIGTERM, sigTermHandler); - openlog("dnsdist", LOG_PID|LOG_NDELAY, LOG_DAEMON); + openlog("dnsdist", LOG_PID | LOG_NDELAY, LOG_DAEMON); #ifdef HAVE_LIBSODIUM if (sodium_init() == -1) { - cerr<<"Unable to initialize crypto library"<(); } ids.qTag->insert_or_assign(std::move(key), std::move(value)); } - void setTag(const std::string& key, const std::string& value) { + void setTag(const std::string& key, const std::string& value) + { if (!ids.qTag) { ids.qTag = std::make_unique(); } ids.qTag->insert_or_assign(key, value); } - void setTag(const std::string& key, std::string&& value) { + void setTag(const std::string& key, std::string&& value) + { if (!ids.qTag) { ids.qTag = std::make_unique(); } @@ -198,8 +202,8 @@ struct DownstreamState; struct DNSResponse : DNSQuestion { - DNSResponse(InternalQueryState& ids_, PacketBuffer& data_, const std::shared_ptr& downstream): - DNSQuestion(ids_, data_), d_downstream(downstream) { } + DNSResponse(InternalQueryState& ids_, PacketBuffer& data_, const std::shared_ptr& downstream) : + DNSQuestion(ids_, data_), d_downstream(downstream) {} DNSResponse(const DNSResponse&) = delete; DNSResponse& operator=(const DNSResponse&) = delete; DNSResponse(DNSResponse&&) = default; @@ -219,10 +223,27 @@ struct DNSResponse : DNSQuestion class DNSAction { public: - enum class Action : uint8_t { Drop, Nxdomain, Refused, Spoof, Allow, HeaderModify, Pool, Delay, Truncate, ServFail, None, NoOp, NoRecurse, SpoofRaw, SpoofPacket }; + enum class Action : uint8_t + { + Drop, + Nxdomain, + Refused, + Spoof, + Allow, + HeaderModify, + Pool, + Delay, + Truncate, + ServFail, + None, + NoOp, + NoRecurse, + SpoofRaw, + SpoofPacket + }; static std::string typeToString(const Action& action) { - switch(action) { + switch (action) { case Action::Drop: return "Drop"; case Action::Nxdomain: @@ -257,7 +278,7 @@ public: return "Unknown"; } - virtual Action operator()(DNSQuestion*, string* ruleresult) const =0; + virtual Action operator()(DNSQuestion*, string* ruleresult) const = 0; virtual ~DNSAction() { } @@ -274,8 +295,17 @@ public: class DNSResponseAction { public: - enum class Action : uint8_t { Allow, Delay, Drop, HeaderModify, ServFail, Truncate, None }; - virtual Action operator()(DNSResponse*, string* ruleresult) const =0; + enum class Action : uint8_t + { + Allow, + Delay, + Drop, + HeaderModify, + ServFail, + Truncate, + None + }; + virtual Action operator()(DNSResponse*, string* ruleresult) const = 0; virtual ~DNSResponseAction() { } @@ -287,22 +317,26 @@ public: struct DynBlock { - DynBlock(): action(DNSAction::Action::None), warning(false) + DynBlock() : + action(DNSAction::Action::None), warning(false) { until.tv_sec = 0; until.tv_nsec = 0; } - DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_): reason(reason_), domain(domain_), until(until_), action(action_), warning(false) + DynBlock(const std::string& reason_, const struct timespec& until_, const DNSName& domain_, DNSAction::Action action_) : + reason(reason_), domain(domain_), until(until_), action(action_), warning(false) { } - DynBlock(const DynBlock& rhs): reason(rhs.reason), domain(rhs.domain), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) + DynBlock(const DynBlock& rhs) : + reason(rhs.reason), domain(rhs.domain), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) { blocks.store(rhs.blocks); } - DynBlock(DynBlock&& rhs): reason(std::move(rhs.reason)), domain(std::move(rhs.domain)), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) + DynBlock(DynBlock&& rhs) : + reason(std::move(rhs.reason)), domain(std::move(rhs.domain)), until(rhs.until), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) { blocks.store(rhs.blocks); } @@ -342,7 +376,7 @@ struct DynBlock extern GlobalStateHolder> g_dynblockNMG; -extern vector > g_confDelta; +extern vector> g_confDelta; using pdns::stat_t; @@ -353,7 +387,8 @@ public: { } - BasicQPSLimiter(unsigned int burst): d_tokens(burst) + BasicQPSLimiter(unsigned int burst) : + d_tokens(burst) { d_prev.start(); } @@ -377,7 +412,7 @@ public: auto delta = d_prev.udiffAndSet(); if (delta > 0.0) { // time, frequently, does go backwards.. - d_tokens += 1.0 * rate * (delta/1000000.0); + d_tokens += 1.0 * rate * (delta / 1000000.0); } if (d_tokens > burst) { @@ -410,11 +445,13 @@ protected: class QPSLimiter : public BasicQPSLimiter { public: - QPSLimiter(): BasicQPSLimiter() + QPSLimiter() : + BasicQPSLimiter() { } - QPSLimiter(unsigned int rate, unsigned int burst): BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false) + QPSLimiter(unsigned int rate, unsigned int burst) : + BasicQPSLimiter(burst), d_rate(rate), d_burst(burst), d_passthrough(false) { d_prev.start(); } @@ -457,7 +494,8 @@ private: typedef std::unordered_map QueryCountRecords; typedef std::function(const DNSQuestion* dq)> QueryCountFilter; -struct QueryCount { +struct QueryCount +{ QueryCount() { } @@ -477,7 +515,8 @@ class XskWorker; struct ClientState { - ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set& cpus_, bool enableProxyProtocol): cpus(cpus_), interface(itfName), local(local_), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort), d_enableProxyProtocol(enableProxyProtocol) + ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set& cpus_, bool enableProxyProtocol) : + cpus(cpus_), interface(itfName), local(local_), fastOpenQueueSize(fastOpenQueue), tcp(isTCP_), reuseport(doReusePort), d_enableProxyProtocol(enableProxyProtocol) { } @@ -497,11 +536,11 @@ struct ClientState stat_t tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket stat_t tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired) stat_t tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one - stat_t tls10queries{0}; // valid DNS queries received via TLSv1.0 - stat_t tls11queries{0}; // valid DNS queries received via TLSv1.1 - stat_t tls12queries{0}; // valid DNS queries received via TLSv1.2 - stat_t tls13queries{0}; // valid DNS queries received via TLSv1.3 - stat_t tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version + stat_t tls10queries{0}; // valid DNS queries received via TLSv1.0 + stat_t tls11queries{0}; // valid DNS queries received via TLSv1.1 + stat_t tls12queries{0}; // valid DNS queries received via TLSv1.2 + stat_t tls13queries{0}; // valid DNS queries received via TLSv1.3 + stat_t tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version pdns::stat_t_trait tcpAvgQueriesPerConnection{0.0}; /* in ms */ pdns::stat_t_trait tcpAvgConnectionDuration{0.0}; @@ -641,7 +680,7 @@ struct ClientState if (d_filter) { detachFilter(getSocket()); for (const auto& [addr, socket] : d_additionalAddresses) { - (void) addr; + (void)addr; if (socket != -1) { detachFilter(socket); } @@ -657,7 +696,7 @@ struct ClientState bpf->addSocket(getSocket()); for (const auto& [addr, socket] : d_additionalAddresses) { - (void) addr; + (void)addr; if (socket != -1) { bpf->addSocket(socket); } @@ -674,7 +713,7 @@ struct ClientState struct CrossProtocolQuery; -struct DownstreamState: public std::enable_shared_from_this +struct DownstreamState : public std::enable_shared_from_this { DownstreamState(const DownstreamState&) = delete; DownstreamState(DownstreamState&&) = delete; @@ -682,15 +721,26 @@ struct DownstreamState: public std::enable_shared_from_this DownstreamState& operator=(DownstreamState&&) = delete; typedef std::function(const DNSName&, uint16_t, uint16_t, dnsheader*)> checkfunc_t; - enum class Availability : uint8_t { Up, Down, Auto, Lazy }; - enum class LazyHealthCheckMode : uint8_t { TimeoutOnly, TimeoutOrServFail }; + enum class Availability : uint8_t + { + Up, + Down, + Auto, + Lazy + }; + enum class LazyHealthCheckMode : uint8_t + { + TimeoutOnly, + TimeoutOrServFail + }; struct Config { Config() { } - Config(const ComboAddress& remote_): remote(remote_) + Config(const ComboAddress& remote_) : + remote(remote_) { } @@ -764,7 +814,8 @@ struct DownstreamState: public std::enable_shared_from_this }; DownstreamState(DownstreamState::Config&& config, std::shared_ptr tlsCtx, bool connect); - DownstreamState(const ComboAddress& remote): DownstreamState(DownstreamState::Config(remote), nullptr, false) + DownstreamState(const ComboAddress& remote) : + DownstreamState(DownstreamState::Config(remote), nullptr, false) { } @@ -778,7 +829,8 @@ struct DownstreamState: public std::enable_shared_from_this stat_t queries{0}; stat_t responses{0}; stat_t nonCompliantResponses{0}; - struct { + struct + { stat_t sendErrors{0}; stat_t reuseds{0}; stat_t queries{0}; @@ -806,6 +858,7 @@ struct DownstreamState: public std::enable_shared_from_this SharedLockGuarded> hashes; LockGuarded> mplexer{nullptr}; + private: LockGuarded> d_idStatesMap; vector idStates; @@ -814,7 +867,12 @@ private: { boost::circular_buffer d_lastResults; time_t d_nextCheck{0}; - enum class LazyStatus: uint8_t { Healthy = 0, PotentialFailure, Failed }; + enum class LazyStatus : uint8_t + { + Healthy = 0, + PotentialFailure, + Failed + }; LazyStatus d_status{LazyStatus::Healthy}; }; LockGuarded d_lazyHealthCheckStats; @@ -855,6 +913,7 @@ private: std::atomic_flag threadStarted; uint8_t consecutiveSuccessfulChecks{0}; bool d_stopped{false}; + public: void updateStatisticsInfo() { @@ -877,7 +936,8 @@ public: return upStatus; } - void setUp() { + void setUp() + { d_config.availability = Availability::Up; } @@ -895,25 +955,29 @@ public: latencyUsec = 0.0; latencyUsecTCP = 0.0; } - void setAuto() { + void setAuto() + { d_config.availability = Availability::Auto; } - void setLazyAuto() { + void setLazyAuto() + { d_config.availability = Availability::Lazy; d_lazyHealthCheckStats.lock()->d_lastResults.set_capacity(d_config.d_lazyHealthCheckSampleSize); } bool healthCheckRequired(std::optional currentTime = std::nullopt); - const string& getName() const { + const string& getName() const + { return d_config.name; } - const string& getNameWithAddr() const { + const string& getNameWithAddr() const + { return d_config.nameWithAddr; } void setName(const std::string& newName) { d_config.name = newName; - d_config.nameWithAddr = newName.empty() ? d_config.remote.toStringWithPort() : (d_config.name + " (" + d_config.remote.toStringWithPort()+ ")"); + d_config.nameWithAddr = newName.empty() ? d_config.remote.toStringWithPort() : (d_config.name + " (" + d_config.remote.toStringWithPort() + ")"); } string getStatus() const @@ -1032,7 +1096,7 @@ extern std::string g_outputBuffer; // locking for this is ok, as locked by g_lua class DNSRule { public: - virtual ~DNSRule () + virtual ~DNSRule() { } virtual bool matches(const DNSQuestion* dq) const = 0; @@ -1042,7 +1106,8 @@ public: struct ServerPool { - ServerPool(): d_servers(std::make_shared()) + ServerPool() : + d_servers(std::make_shared()) { } @@ -1076,7 +1141,8 @@ private: bool d_useECS{false}; }; -enum ednsHeaderFlags { +enum ednsHeaderFlags +{ EDNS_HEADER_FLAG_NONE = 0, EDNS_HEADER_FLAG_DO = 32768 }; @@ -1105,11 +1171,11 @@ extern DNSAction::Action g_dynBlockAction; extern GlobalStateHolder g_policy; extern GlobalStateHolder g_dstates; extern GlobalStateHolder g_pools; -extern GlobalStateHolder > g_ruleactions; -extern GlobalStateHolder > g_respruleactions; -extern GlobalStateHolder > g_cachehitrespruleactions; -extern GlobalStateHolder > g_selfansweredrespruleactions; -extern GlobalStateHolder > g_cacheInsertedRespRuleActions; +extern GlobalStateHolder> g_ruleactions; +extern GlobalStateHolder> g_respruleactions; +extern GlobalStateHolder> g_cachehitrespruleactions; +extern GlobalStateHolder> g_selfansweredrespruleactions; +extern GlobalStateHolder> g_cacheInsertedRespRuleActions; extern GlobalStateHolder g_ACL; extern ComboAddress g_serverControl; // not changed during runtime @@ -1142,30 +1208,31 @@ extern uint32_t g_socketUDPSendBuffer; extern uint32_t g_socketUDPRecvBuffer; extern shared_ptr g_defaultBPFFilter; -extern std::vector > g_dynBPFFilters; +extern std::vector> g_dynBPFFilters; struct LocalHolders { - LocalHolders(): acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(g_ruleactions.getLocal()), cacheHitRespRuleactions(g_cachehitrespruleactions.getLocal()), cacheInsertedRespRuleActions(g_cacheInsertedRespRuleActions.getLocal()), selfAnsweredRespRuleactions(g_selfansweredrespruleactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal()) + LocalHolders() : + acl(g_ACL.getLocal()), policy(g_policy.getLocal()), ruleactions(g_ruleactions.getLocal()), cacheHitRespRuleactions(g_cachehitrespruleactions.getLocal()), cacheInsertedRespRuleActions(g_cacheInsertedRespRuleActions.getLocal()), selfAnsweredRespRuleactions(g_selfansweredrespruleactions.getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal()), pools(g_pools.getLocal()) { } LocalStateHolder acl; LocalStateHolder policy; - LocalStateHolder > ruleactions; - LocalStateHolder > cacheHitRespRuleactions; - LocalStateHolder > cacheInsertedRespRuleActions; - LocalStateHolder > selfAnsweredRespRuleactions; + LocalStateHolder> ruleactions; + LocalStateHolder> cacheHitRespRuleactions; + LocalStateHolder> cacheInsertedRespRuleActions; + LocalStateHolder> selfAnsweredRespRuleactions; LocalStateHolder servers; - LocalStateHolder > dynNMGBlock; - LocalStateHolder > dynSMTBlock; + LocalStateHolder> dynNMGBlock; + LocalStateHolder> dynSMTBlock; LocalStateHolder pools; }; void tcpAcceptorThread(const std::vector& states); void setLuaNoSideEffect(); // if nothing has been declared, set that there are no side effects -void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls +void setLuaSideEffect(); // set to report a side effect, cancelling all _no_ side effect calls bool getLuaNoSideEffect(); // set if there were only explicit declarations of _no_ side effect void resetLuaSideEffect(); // reset to indeterminate state @@ -1187,7 +1254,13 @@ 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 { Drop, SendAnswer, PassToBackend, Asynchronous }; +enum class ProcessQueryResult : uint8_t +{ + Drop, + SendAnswer, + PassToBackend, + Asynchronous +}; ProcessQueryResult processQuery(DNSQuestion& dq, LocalHolders& holders, std::shared_ptr& selectedBackend); ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders, std::shared_ptr& selectedBackend); bool processResponse(PacketBuffer& response, const std::vector& respRuleActions, const std::vector& insertedRespRuleActions, DNSResponse& dr, bool muted); diff --git a/pdns/dnsdistdist/test-dnsdist_cc.cc b/pdns/dnsdistdist/test-dnsdist_cc.cc index 90a513fc88..1254c7e357 100644 --- a/pdns/dnsdistdist/test-dnsdist_cc.cc +++ b/pdns/dnsdistdist/test-dnsdist_cc.cc @@ -63,7 +63,8 @@ bool assignOutgoingUDPQueryToBackend(std::shared_ptr& downstrea return true; } -namespace dnsdist { +namespace dnsdist +{ std::unique_ptr getInternalQueryFromDQ(DNSQuestion& dq, bool isResponse) { return nullptr; @@ -92,7 +93,7 @@ BOOST_AUTO_TEST_SUITE(test_dnsdist_cc) static const uint16_t ECSSourcePrefixV4 = 24; static const uint16_t ECSSourcePrefixV6 = 56; -static void validateQuery(const PacketBuffer& packet, bool hasEdns=true, bool hasXPF=false, uint16_t additionals=0, uint16_t answers=0, uint16_t authorities=0) +static void validateQuery(const PacketBuffer& packet, bool hasEdns = true, bool hasXPF = false, uint16_t additionals = 0, uint16_t answers = 0, uint16_t authorities = 0) { MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -125,7 +126,7 @@ static void validateECS(const PacketBuffer& packet, const ComboAddress& expected BOOST_CHECK_EQUAL(expectedOption.substr(EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE), std::string(ecsOption->second.values.at(0).content, ecsOption->second.values.at(0).size)); } -static void validateResponse(const PacketBuffer& packet, bool hasEdns, uint8_t additionalCount=0) +static void validateResponse(const PacketBuffer& packet, bool hasEdns, uint8_t additionalCount = 0) { MOADNSParser mdp(false, reinterpret_cast(packet.data()), packet.size()); @@ -372,7 +373,7 @@ BOOST_AUTO_TEST_CASE(addECSWithoutEDNSAlreadyParsed) auto packet = query; - ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, &ids.qclass); + ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, &ids.qclass); BOOST_CHECK_EQUAL(ids.qname, name); BOOST_CHECK(ids.qtype == QType::A); BOOST_CHECK(ids.qclass == QClass::IN); @@ -411,7 +412,8 @@ BOOST_AUTO_TEST_CASE(addECSWithoutEDNSAlreadyParsed) validateECS(packet, ids.origRemote); } -BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECS) { +BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECS) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote; @@ -457,7 +459,8 @@ BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECS) { validateQuery(packet); } -BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECSAlreadyParsed) { +BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECSAlreadyParsed) +{ InternalQueryState ids; ids.origRemote = ComboAddress("2001:DB8::1"); ids.protocol = dnsdist::Protocol::DoUDP; @@ -510,7 +513,8 @@ BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECSAlreadyParsed) { validateECS(packet, ids.origRemote); } -BOOST_AUTO_TEST_CASE(replaceECSWithSameSize) { +BOOST_AUTO_TEST_CASE(replaceECSWithSameSize) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -547,7 +551,8 @@ BOOST_AUTO_TEST_CASE(replaceECSWithSameSize) { validateECS(packet, remote); } -BOOST_AUTO_TEST_CASE(replaceECSWithSameSizeAlreadyParsed) { +BOOST_AUTO_TEST_CASE(replaceECSWithSameSizeAlreadyParsed) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -593,7 +598,8 @@ BOOST_AUTO_TEST_CASE(replaceECSWithSameSizeAlreadyParsed) { validateECS(packet, remote); } -BOOST_AUTO_TEST_CASE(replaceECSWithSmaller) { +BOOST_AUTO_TEST_CASE(replaceECSWithSmaller) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -629,7 +635,8 @@ BOOST_AUTO_TEST_CASE(replaceECSWithSmaller) { validateECS(packet, remote); } -BOOST_AUTO_TEST_CASE(replaceECSWithLarger) { +BOOST_AUTO_TEST_CASE(replaceECSWithLarger) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -684,7 +691,8 @@ BOOST_AUTO_TEST_CASE(replaceECSWithLarger) { validateQuery(packet); } -BOOST_AUTO_TEST_CASE(replaceECSFollowedByTSIG) { +BOOST_AUTO_TEST_CASE(replaceECSFollowedByTSIG) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -738,7 +746,8 @@ BOOST_AUTO_TEST_CASE(replaceECSFollowedByTSIG) { validateQuery(packet, true, false, 1); } -BOOST_AUTO_TEST_CASE(replaceECSAfterAN) { +BOOST_AUTO_TEST_CASE(replaceECSAfterAN) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -793,7 +802,8 @@ BOOST_AUTO_TEST_CASE(replaceECSAfterAN) { validateQuery(packet, true, false, 0, 1, 0); } -BOOST_AUTO_TEST_CASE(replaceECSAfterAuth) { +BOOST_AUTO_TEST_CASE(replaceECSAfterAuth) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -848,7 +858,8 @@ BOOST_AUTO_TEST_CASE(replaceECSAfterAuth) { validateQuery(packet, true, false, 0, 0, 1); } -BOOST_AUTO_TEST_CASE(replaceECSBetweenTwoRecords) { +BOOST_AUTO_TEST_CASE(replaceECSBetweenTwoRecords) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -904,7 +915,8 @@ BOOST_AUTO_TEST_CASE(replaceECSBetweenTwoRecords) { validateQuery(packet, true, false, 2); } -BOOST_AUTO_TEST_CASE(insertECSInEDNSBetweenTwoRecords) { +BOOST_AUTO_TEST_CASE(insertECSInEDNSBetweenTwoRecords) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -955,7 +967,8 @@ BOOST_AUTO_TEST_CASE(insertECSInEDNSBetweenTwoRecords) { validateQuery(packet, true, false, 2); } -BOOST_AUTO_TEST_CASE(insertECSAfterTSIG) { +BOOST_AUTO_TEST_CASE(insertECSAfterTSIG) +{ bool ednsAdded = false; bool ecsAdded = false; ComboAddress remote("192.168.1.25"); @@ -1004,8 +1017,8 @@ BOOST_AUTO_TEST_CASE(insertECSAfterTSIG) { validateQuery(packet, true, false); } - -BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst) { +BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst) +{ DNSName name("www.powerdns.com."); PacketBuffer response; @@ -1025,7 +1038,7 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); size_t const ednsOptRRSize = sizeof(struct dnsrecordheader) + 1 /* root in OPT RR */; @@ -1034,7 +1047,8 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst) { validateResponse(newResponse, false, 1); } -BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary) { +BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary) +{ DNSName name("www.powerdns.com."); PacketBuffer response; @@ -1057,7 +1071,7 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); size_t const ednsOptRRSize = sizeof(struct dnsrecordheader) + 1 /* root in OPT RR */; @@ -1066,7 +1080,8 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary) { validateResponse(newResponse, false, 2); } -BOOST_AUTO_TEST_CASE(removeEDNSWhenLast) { +BOOST_AUTO_TEST_CASE(removeEDNSWhenLast) +{ DNSName name("www.powerdns.com."); PacketBuffer response; @@ -1088,7 +1103,7 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenLast) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); size_t const ednsOptRRSize = sizeof(struct dnsrecordheader) + 1 /* root in OPT RR */; @@ -1097,7 +1112,8 @@ BOOST_AUTO_TEST_CASE(removeEDNSWhenLast) { validateResponse(newResponse, false, 1); } -BOOST_AUTO_TEST_CASE(removeECSWhenOnlyOption) { +BOOST_AUTO_TEST_CASE(removeECSWhenOnlyOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1130,21 +1146,22 @@ BOOST_AUTO_TEST_CASE(removeECSWhenOnlyOption) { size_t responseLen = response.size(); size_t existingOptLen = optLen; BOOST_CHECK(existingOptLen < responseLen); - res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); + res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); BOOST_CHECK_EQUAL(res, 0); BOOST_CHECK_EQUAL(optLen, existingOptLen - (origECSOptionStr.size() + 4)); responseLen -= (existingOptLen - optLen); unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(response, true, 1); } -BOOST_AUTO_TEST_CASE(removeECSWhenFirstOption) { +BOOST_AUTO_TEST_CASE(removeECSWhenFirstOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1180,21 +1197,22 @@ BOOST_AUTO_TEST_CASE(removeECSWhenFirstOption) { size_t responseLen = response.size(); size_t existingOptLen = optLen; BOOST_CHECK(existingOptLen < responseLen); - res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); + res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); BOOST_CHECK_EQUAL(res, 0); BOOST_CHECK_EQUAL(optLen, existingOptLen - (origECSOptionStr.size() + 4)); responseLen -= (existingOptLen - optLen); unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(response, true, 1); } -BOOST_AUTO_TEST_CASE(removeECSWhenIntermediaryOption) { +BOOST_AUTO_TEST_CASE(removeECSWhenIntermediaryOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1234,21 +1252,22 @@ BOOST_AUTO_TEST_CASE(removeECSWhenIntermediaryOption) { size_t responseLen = response.size(); size_t existingOptLen = optLen; BOOST_CHECK(existingOptLen < responseLen); - res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); + res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); BOOST_CHECK_EQUAL(res, 0); BOOST_CHECK_EQUAL(optLen, existingOptLen - (origECSOptionStr.size() + 4)); responseLen -= (existingOptLen - optLen); unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(response, true, 1); } -BOOST_AUTO_TEST_CASE(removeECSWhenLastOption) { +BOOST_AUTO_TEST_CASE(removeECSWhenLastOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1284,21 +1303,22 @@ BOOST_AUTO_TEST_CASE(removeECSWhenLastOption) { size_t responseLen = response.size(); size_t existingOptLen = optLen; BOOST_CHECK(existingOptLen < responseLen); - res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); + res = removeEDNSOptionFromOPT(reinterpret_cast(response.data()) + optStart, &optLen, EDNSOptionCode::ECS); BOOST_CHECK_EQUAL(res, 0); BOOST_CHECK_EQUAL(optLen, existingOptLen - (origECSOptionStr.size() + 4)); responseLen -= (existingOptLen - optLen); unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)response.data(), responseLen, sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(response, true, 1); } -BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenOnlyOption) { +BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenOnlyOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1328,14 +1348,15 @@ BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenOnlyOption) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(newResponse, true, 1); } -BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenFirstOption) { +BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenFirstOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1368,14 +1389,15 @@ BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenFirstOption) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(newResponse, true, 1); } -BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenIntermediaryOption) { +BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenIntermediaryOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1410,14 +1432,15 @@ BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenIntermediaryOption) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(newResponse, true, 1); } -BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenLastOption) { +BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenLastOption) +{ DNSName name("www.powerdns.com."); ComboAddress origRemote("127.0.0.1"); @@ -1450,14 +1473,14 @@ BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenLastOption) { unsigned int consumed = 0; uint16_t qtype; - DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); + DNSName qname((const char*)newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed); BOOST_CHECK_EQUAL(qname, name); BOOST_CHECK(qtype == QType::A); validateResponse(newResponse, true, 1); } -static DNSQuestion turnIntoResponse(InternalQueryState& ids, PacketBuffer& query, bool resizeBuffer=true) +static DNSQuestion turnIntoResponse(InternalQueryState& ids, PacketBuffer& query, bool resizeBuffer = true) { if (resizeBuffer) { query.resize(4096); @@ -1486,7 +1509,8 @@ static int getZ(const DNSName& qname, const uint16_t qtype, const uint16_t qclas return getEDNSZ(dq); } -BOOST_AUTO_TEST_CASE(test_getEDNSZ) { +BOOST_AUTO_TEST_CASE(test_getEDNSZ) +{ uint16_t z; uint16_t udpPayloadSize; @@ -1554,7 +1578,7 @@ BOOST_AUTO_TEST_CASE(test_getEDNSZ) { BOOST_CHECK_EQUAL(udpPayloadSize, 512); } - { + { /* valid EDNS, options, DO not set */ PacketBuffer query; GenericDNSPacketWriter pw(query, qname, qtype, qclass, 0); @@ -1579,10 +1603,10 @@ BOOST_AUTO_TEST_CASE(test_getEDNSZ) { BOOST_CHECK_EQUAL(z, EDNS_HEADER_FLAG_DO); BOOST_CHECK_EQUAL(udpPayloadSize, 512); } - } -BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) { +BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) +{ InternalQueryState ids; ids.qname = DNSName("www.powerdns.com."); ids.qtype = QType::A; @@ -1688,7 +1712,8 @@ BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse) { } } -BOOST_AUTO_TEST_CASE(test_getEDNSOptionsStart) { +BOOST_AUTO_TEST_CASE(test_getEDNSOptionsStart) +{ const DNSName qname("www.powerdns.com."); const uint16_t qtype = QType::A; const uint16_t qclass = QClass::IN; @@ -1763,10 +1788,10 @@ BOOST_AUTO_TEST_CASE(test_getEDNSOptionsStart) { BOOST_CHECK_EQUAL(optRDPosition, optRDExpectedOffset); BOOST_CHECK_EQUAL(remaining, query.size() - optRDExpectedOffset); } - } -BOOST_AUTO_TEST_CASE(test_isEDNSOptionInOpt) { +BOOST_AUTO_TEST_CASE(test_isEDNSOptionInOpt) +{ auto locateEDNSOption = [](const PacketBuffer& query, uint16_t code, size_t* optContentStart, uint16_t* optContentLen) { uint16_t optStart; @@ -1932,7 +1957,8 @@ BOOST_AUTO_TEST_CASE(test_isEDNSOptionInOpt) { } } -BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { +BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) +{ InternalQueryState ids; ids.origRemote = ComboAddress("192.0.2.1"); ids.protocol = dnsdist::Protocol::DoUDP; @@ -1957,7 +1983,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, false)); BOOST_CHECK(packet.size() > query.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -1979,7 +2005,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, false)); BOOST_CHECK(packet.size() > queryWithEDNS.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2005,7 +2031,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, false)); BOOST_CHECK(packet.size() > query.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2027,7 +2053,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, false)); BOOST_CHECK(packet.size() > queryWithEDNS.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2055,8 +2081,8 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , - 5, true)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, + 5, true)); BOOST_CHECK(packet.size() > query.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2078,7 +2104,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, true)); BOOST_CHECK(packet.size() > queryWithEDNS.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2104,7 +2130,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, true)); BOOST_CHECK(packet.size() > query.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2126,7 +2152,7 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { ids.qname = DNSName(reinterpret_cast(packet.data()), packet.size(), sizeof(dnsheader), false, &ids.qtype, nullptr); DNSQuestion dq(ids, packet); - BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true)); + BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4, 5, true)); BOOST_CHECK(packet.size() > queryWithEDNS.size()); MOADNSParser mdp(true, reinterpret_cast(packet.data()), packet.size()); @@ -2145,7 +2171,8 @@ BOOST_AUTO_TEST_CASE(test_setNegativeAndAdditionalSOA) { } } -BOOST_AUTO_TEST_CASE(getEDNSOptionsWithoutEDNS) { +BOOST_AUTO_TEST_CASE(getEDNSOptionsWithoutEDNS) +{ InternalQueryState ids; ids.origRemote = ComboAddress("192.168.1.25"); ids.protocol = dnsdist::Protocol::DoUDP; diff --git a/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc b/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc index 3fa1eaae05..968e6c2d7e 100644 --- a/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc @@ -198,7 +198,7 @@ private: static ssize_t send_callback(nghttp2_session* session, const uint8_t* data, size_t length, int flags, void* user_data) { auto* conn = static_cast(user_data); - //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): nghttp2 API + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): nghttp2 API conn->d_clientOutBuffer.insert(conn->d_clientOutBuffer.end(), data, data + length); return static_cast(length); } @@ -233,7 +233,7 @@ private: { auto* conn = static_cast(user_data); auto& response = conn->d_responses[stream_id]; - //NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): nghttp2 API + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): nghttp2 API response.insert(response.end(), data, data + len); return 0; } @@ -247,7 +247,7 @@ private: try { uint16_t responseCode{0}; auto expected = s_connectionContexts.at(conn->d_connectionID).d_responseCodes.at((frame->hd.stream_id - 1) / 2); - //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): nghttp2 API + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): nghttp2 API pdns::checked_stoi_into(responseCode, std::string(reinterpret_cast(value), valuelen)); conn->d_responseCodes[frame->hd.stream_id] = responseCode; if (responseCode != expected) { @@ -350,10 +350,10 @@ public: BOOST_REQUIRE_GE(buffer.size(), toRead); - //NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) std::copy(externalBuffer.begin(), externalBuffer.begin() + toRead, buffer.begin() + pos); pos += toRead; - //NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) externalBuffer.erase(externalBuffer.begin(), externalBuffer.begin() + toRead); return step.nextState; diff --git a/pdns/dnsdistdist/test-dnsdistpacketcache_cc.cc b/pdns/dnsdistdist/test-dnsdistpacketcache_cc.cc index 42d2bad4a1..ae72cf267d 100644 --- a/pdns/dnsdistdist/test-dnsdistpacketcache_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistpacketcache_cc.cc @@ -20,7 +20,8 @@ BOOST_AUTO_TEST_SUITE(test_dnsdistpacketcache_cc) static bool receivedOverUDP = true; -BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { +BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) +{ const size_t maxEntries = 150000; DNSDistPacketCache PC(maxEntries, 86400, 1); BOOST_CHECK_EQUAL(PC.getSize(), 0U); @@ -36,7 +37,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { try { for (counter = 0; counter < 100000; ++counter) { - auto a = DNSName(std::to_string(counter))+DNSName(" hello"); + auto a = DNSName(std::to_string(counter)) + DNSName(" hello"); ids.qname = a; PacketBuffer query; @@ -77,10 +78,10 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { BOOST_CHECK_EQUAL(skipped, PC.getInsertCollisions()); BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped); - size_t deleted=0; - size_t delcounter=0; - for (delcounter=0; delcounter < counter/1000; ++delcounter) { - ids.qname = DNSName(std::to_string(delcounter))+DNSName(" hello"); + size_t deleted = 0; + size_t delcounter = 0; + for (delcounter = 0; delcounter < counter / 1000; ++delcounter) { + ids.qname = DNSName(std::to_string(delcounter)) + DNSName(" hello"); PacketBuffer query; GenericDNSPacketWriter pwQ(query, ids.qname, QType::A, QClass::IN, 0); pwQ.getHeader()->rd = 1; @@ -96,10 +97,10 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { } BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped - deleted); - size_t matches=0; - size_t expected=counter-skipped-deleted; + size_t matches = 0; + size_t expected = counter - skipped - deleted; for (; delcounter < counter; ++delcounter) { - ids.qname = DNSName(std::to_string(delcounter))+DNSName(" hello"); + ids.qname = DNSName(std::to_string(delcounter)) + DNSName(" hello"); PacketBuffer query; GenericDNSPacketWriter pwQ(query, ids.qname, QType::A, QClass::IN, 0); pwQ.getHeader()->rd = 1; @@ -124,12 +125,13 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) { BOOST_CHECK_EQUAL(PC.purgeExpired(0, now), 0U); } catch (const PDNSException& e) { - cerr<<"Had error: "<id, &key, subnet, dnssecOK, receivedOverUDP, 0, true, allowTruncated); BOOST_CHECK_EQUAL(found, false); -} - catch(const PDNSException& e) { - cerr<<"Had error: "< pwQ(query, ids.qname, QType::A, QClass::IN, 0); pwQ.getHeader()->rd = 1; @@ -697,8 +705,8 @@ static void threadMangler(unsigned int offset) g_PC.insert(key, subnet, *(getFlagsFromDNSHeader(dnsQuestion.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none); } } - catch(PDNSException& e) { - cerr<<"Had error: "< pwQ(query, ids.qname, QType::A, QClass::IN, 0); pwQ.getHeader()->rd = 1; @@ -727,21 +734,22 @@ static void threadReader(unsigned int offset) DNSQuestion dnsQuestion(ids, query); bool found = g_PC.get(dnsQuestion, 0, &key, subnet, dnssecOK, receivedOverUDP); if (!found) { - g_missing++; + g_missing++; } } } - catch(PDNSException& e) { - cerr<<"Had error in threadReader: "< threads; for (int i = 0; i < 4; ++i) { - threads.push_back(std::thread(threadMangler, i*1000000UL)); + threads.push_back(std::thread(threadMangler, i * 1000000UL)); } for (auto& t : threads) { @@ -751,10 +759,10 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded) { threads.clear(); BOOST_CHECK_EQUAL(g_PC.getSize() + g_PC.getDeferredInserts() + g_PC.getInsertCollisions(), 400000U); - BOOST_CHECK_SMALL(1.0*g_PC.getInsertCollisions(), 10000.0); + BOOST_CHECK_SMALL(1.0 * g_PC.getInsertCollisions(), 10000.0); for (int i = 0; i < 4; ++i) { - threads.push_back(std::thread(threadReader, i*1000000UL)); + threads.push_back(std::thread(threadReader, i * 1000000UL)); } for (auto& t : threads) { @@ -763,14 +771,14 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded) { BOOST_CHECK((g_PC.getDeferredInserts() + g_PC.getDeferredLookups() + g_PC.getInsertCollisions()) >= g_missing); } - catch(PDNSException& e) { - cerr<<"Had error: "< xfrTypes = { QType::AXFR, QType::IXFR }; + const std::set xfrTypes = {QType::AXFR, QType::IXFR}; for (const auto& type : xfrTypes) { bool dnssecOK = false; InternalQueryState ids;