diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 93db38965475..fc0a25ffd646 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -144,6 +144,7 @@ dnsdist_SOURCES = \ dns.cc dns.hh \ dns_random.hh \ dnscrypt.cc dnscrypt.hh \ + dnsdist-actions.hh \ dnsdist-async.cc dnsdist-async.hh \ dnsdist-backend.cc dnsdist-backend.hh \ dnsdist-backoff.hh \ diff --git a/pdns/dnsdistdist/dnsdist-actions.hh b/pdns/dnsdistdist/dnsdist-actions.hh new file mode 100644 index 000000000000..5bb08a0c6eac --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-actions.hh @@ -0,0 +1,128 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +/* so what could you do: + drop, + fake up nxdomain, + provide actual answer, + allow & and stop processing, + continue processing, + modify header: (servfail|refused|notimp), set TC=1, + send to pool */ + +struct DNSQuestion; +struct DNSResponse; + +class DNSAction +{ +public: + enum class Action : uint8_t + { + Drop, + Nxdomain, + Refused, + Spoof, + Allow, + HeaderModify, + Pool, + Delay, + Truncate, + ServFail, + None, + NoOp, + NoRecurse, + SpoofRaw, + SpoofPacket, + SetTag, + }; + static std::string typeToString(const Action& action) + { + switch (action) { + case Action::Drop: + return "Drop"; + case Action::Nxdomain: + return "Send NXDomain"; + case Action::Refused: + return "Send Refused"; + case Action::Spoof: + return "Spoof an answer"; + case Action::SpoofPacket: + return "Spoof a raw answer from bytes"; + case Action::SpoofRaw: + return "Spoof an answer from raw bytes"; + case Action::Allow: + return "Allow"; + case Action::HeaderModify: + return "Modify the header"; + case Action::Pool: + return "Route to a pool"; + case Action::Delay: + return "Delay"; + case Action::Truncate: + return "Truncate over UDP"; + case Action::ServFail: + return "Send ServFail"; + case Action::SetTag: + return "Set Tag"; + case Action::None: + case Action::NoOp: + return "Do nothing"; + case Action::NoRecurse: + return "Set rd=0"; + } + + return "Unknown"; + } + + virtual Action operator()(DNSQuestion*, std::string* ruleresult) const = 0; + virtual ~DNSAction() = default; + virtual std::string toString() const = 0; + virtual std::map getStats() const + { + return {{}}; + } + virtual void reload() + { + } +}; + +class DNSResponseAction +{ +public: + enum class Action : uint8_t + { + Allow, + Delay, + Drop, + HeaderModify, + ServFail, + Truncate, + None + }; + virtual Action operator()(DNSResponse*, std::string* ruleresult) const = 0; + virtual ~DNSResponseAction() = default; + virtual std::string toString() const = 0; + virtual void reload() + { + } +}; diff --git a/pdns/dnsdistdist/dnsdist-async.cc b/pdns/dnsdistdist/dnsdist-async.cc index b76622b84c97..84095c4a2e2b 100644 --- a/pdns/dnsdistdist/dnsdist-async.cc +++ b/pdns/dnsdistdist/dnsdist-async.cc @@ -22,6 +22,7 @@ #include "dnsdist-async.hh" #include "dnsdist-internal-queries.hh" #include "dolog.hh" +#include "mplexer.hh" #include "threadname.hh" namespace dnsdist diff --git a/pdns/dnsdistdist/dnsdist-async.hh b/pdns/dnsdistdist/dnsdist-async.hh index c0b8453ae6be..7a337d25b54f 100644 --- a/pdns/dnsdistdist/dnsdist-async.hh +++ b/pdns/dnsdistdist/dnsdist-async.hh @@ -59,7 +59,7 @@ private: uint16_t d_queryID; }; - typedef multi_index_container< + using content_t = multi_index_container< Entry, indexed_by< ordered_unique, @@ -68,8 +68,7 @@ private: member, member>>, ordered_non_unique, - member>>> - content_t; + member>>>; static void pickupExpired(content_t&, const struct timeval& now, std::list>>& expiredEvents); static struct timeval getNextTTD(const content_t&); diff --git a/pdns/dnsdistdist/dnsdist-carbon.cc b/pdns/dnsdistdist/dnsdist-carbon.cc index 6fa97a5341ef..5df2049352d2 100644 --- a/pdns/dnsdistdist/dnsdist-carbon.cc +++ b/pdns/dnsdistdist/dnsdist-carbon.cc @@ -24,6 +24,7 @@ #endif #include "dnsdist-carbon.hh" +#include "dnsdist-cache.hh" #include "dnsdist.hh" #include "dnsdist-backoff.hh" #include "dnsdist-configuration.hh" diff --git a/pdns/dnsdistdist/dnsdist-configuration.hh b/pdns/dnsdistdist/dnsdist-configuration.hh index bca05ef2a0e3..0c81741addcf 100644 --- a/pdns/dnsdistdist/dnsdist-configuration.hh +++ b/pdns/dnsdistdist/dnsdist-configuration.hh @@ -29,117 +29,12 @@ #include "config.h" #include "credentials.hh" +#include "dnsdist-actions.hh" #include "dnsdist-carbon.hh" #include "dnsdist-query-count.hh" #include "dnsdist-rule-chains.hh" #include "iputils.hh" -/* so what could you do: - drop, - fake up nxdomain, - provide actual answer, - allow & and stop processing, - continue processing, - modify header: (servfail|refused|notimp), set TC=1, - send to pool */ - -struct DNSQuestion; -struct DNSResponse; - -class DNSAction -{ -public: - enum class Action : uint8_t - { - Drop, - Nxdomain, - Refused, - Spoof, - Allow, - HeaderModify, - Pool, - Delay, - Truncate, - ServFail, - None, - NoOp, - NoRecurse, - SpoofRaw, - SpoofPacket, - SetTag, - }; - static std::string typeToString(const Action& action) - { - switch (action) { - case Action::Drop: - return "Drop"; - case Action::Nxdomain: - return "Send NXDomain"; - case Action::Refused: - return "Send Refused"; - case Action::Spoof: - return "Spoof an answer"; - case Action::SpoofPacket: - return "Spoof a raw answer from bytes"; - case Action::SpoofRaw: - return "Spoof an answer from raw bytes"; - case Action::Allow: - return "Allow"; - case Action::HeaderModify: - return "Modify the header"; - case Action::Pool: - return "Route to a pool"; - case Action::Delay: - return "Delay"; - case Action::Truncate: - return "Truncate over UDP"; - case Action::ServFail: - return "Send ServFail"; - case Action::SetTag: - return "Set Tag"; - case Action::None: - case Action::NoOp: - return "Do nothing"; - case Action::NoRecurse: - return "Set rd=0"; - } - - return "Unknown"; - } - - virtual Action operator()(DNSQuestion*, std::string* ruleresult) const = 0; - virtual ~DNSAction() = default; - virtual std::string toString() const = 0; - virtual std::map getStats() const - { - return {{}}; - } - virtual void reload() - { - } -}; - -class DNSResponseAction -{ -public: - enum class Action : uint8_t - { - Allow, - Delay, - Drop, - HeaderModify, - ServFail, - Truncate, - None - }; - virtual Action operator()(DNSResponse*, std::string* ruleresult) const = 0; - virtual ~DNSResponseAction() = default; - virtual std::string toString() const = 0; - virtual void reload() - { - } -}; - class ServerPolicy; struct ServerPool; struct DownstreamState; diff --git a/pdns/dnsdistdist/dnsdist-dnsquestion.cc b/pdns/dnsdistdist/dnsdist-dnsquestion.cc index 7090f56e11e2..dde891b90079 100644 --- a/pdns/dnsdistdist/dnsdist-dnsquestion.cc +++ b/pdns/dnsdistdist/dnsdist-dnsquestion.cc @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "dnsdist.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-dnsparser.hh" std::string DNSQuestion::getTrailingData() const diff --git a/pdns/dnsdistdist/dnsdist-dynblocks.hh b/pdns/dnsdistdist/dnsdist-dynblocks.hh index 9a644b798352..f700e16416a1 100644 --- a/pdns/dnsdistdist/dnsdist-dynblocks.hh +++ b/pdns/dnsdistdist/dnsdist-dynblocks.hh @@ -68,6 +68,73 @@ struct dnsdist_ffi_stat_node_t SMTBlockParameters& d_blockParameters; }; +struct DynBlock +{ + DynBlock() + { + 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_) + { + } + + DynBlock(const DynBlock& rhs) : + reason(rhs.reason), domain(rhs.domain), until(rhs.until), tagSettings(rhs.tagSettings), 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), tagSettings(std::move(rhs.tagSettings)), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) + { + blocks.store(rhs.blocks); + } + + DynBlock& operator=(const DynBlock& rhs) + { + reason = rhs.reason; + until = rhs.until; + domain = rhs.domain; + action = rhs.action; + blocks.store(rhs.blocks); + warning = rhs.warning; + bpf = rhs.bpf; + tagSettings = rhs.tagSettings; + return *this; + } + + DynBlock& operator=(DynBlock&& rhs) + { + reason = std::move(rhs.reason); + until = rhs.until; + domain = std::move(rhs.domain); + action = rhs.action; + blocks.store(rhs.blocks); + warning = rhs.warning; + bpf = rhs.bpf; + tagSettings = std::move(rhs.tagSettings); + return *this; + } + + struct TagSettings + { + std::string d_name; + std::string d_value; + }; + + string reason; + DNSName domain; + timespec until{}; + std::shared_ptr tagSettings{nullptr}; + mutable std::atomic blocks{0}; + DNSAction::Action action{DNSAction::Action::None}; + bool warning{false}; + bool bpf{false}; +}; + using dnsdist_ffi_dynamic_block_inserted_hook = std::function; using ClientAddressDynamicRules = NetmaskTree; using SuffixDynamicRules = SuffixMatchTree; diff --git a/pdns/dnsdistdist/dnsdist-dynbpf.cc b/pdns/dnsdistdist/dnsdist-dynbpf.cc index ab09f6dc0f46..2f76f9fcafdf 100644 --- a/pdns/dnsdistdist/dnsdist-dynbpf.cc +++ b/pdns/dnsdistdist/dnsdist-dynbpf.cc @@ -21,6 +21,8 @@ */ #include "dnsdist-dynbpf.hh" +std::vector> g_dynBPFFilters; + bool DynBPFFilter::block(const ComboAddress& addr, const struct timespec& until) { bool inserted = false; diff --git a/pdns/dnsdistdist/dnsdist-dynbpf.hh b/pdns/dnsdistdist/dnsdist-dynbpf.hh index cfb5d6b3c2ad..c9eca259ed39 100644 --- a/pdns/dnsdistdist/dnsdist-dynbpf.hh +++ b/pdns/dnsdistdist/dnsdist-dynbpf.hh @@ -75,3 +75,5 @@ private: }; LockGuarded d_data; }; + +extern std::vector> g_dynBPFFilters; diff --git a/pdns/dnsdistdist/dnsdist-frontend.cc b/pdns/dnsdistdist/dnsdist-frontend.cc index 20bef4e0047c..8e75ee396f7f 100644 --- a/pdns/dnsdistdist/dnsdist-frontend.cc +++ b/pdns/dnsdistdist/dnsdist-frontend.cc @@ -22,6 +22,7 @@ #include "dnsdist-frontend.hh" #include "dnsdist.hh" +#include "dnsdist-configuration.hh" namespace dnsdist { diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.hh b/pdns/dnsdistdist/dnsdist-lbpolicies.hh index c609536959a7..b92237861d4a 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.hh +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.hh @@ -25,6 +25,7 @@ struct dnsdist_ffi_servers_list_t; struct dnsdist_ffi_server_t; struct dnsdist_ffi_dnsquestion_t; +struct DNSQuestion; struct DownstreamState; struct PerThreadPoliciesState; diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc index f71bf37516de..65470b2b870d 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc @@ -25,6 +25,7 @@ #include "config.h" #include "dnsdist.hh" +#include "dnsdist-cache.hh" #include "dnsdist-lua.hh" #include diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings.cc b/pdns/dnsdistdist/dnsdist-lua-bindings.cc index 52ee81d6a8cb..8c8de1dc7078 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings.cc @@ -23,6 +23,8 @@ #include "config.h" #include "dnsdist.hh" #include "dnsdist-async.hh" +#include "dnsdist-dynblocks.hh" +#include "dnsdist-dynbpf.hh" #include "dnsdist-frontend.hh" #include "dnsdist-lua.hh" #include "dnsdist-resolver.hh" @@ -257,7 +259,9 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.registerFunction("isIPv6", [](const ComboAddress& addr) { return addr.sin4.sin_family == AF_INET6; }); luaCtx.registerFunction("isMappedIPv4", [](const ComboAddress& addr) { return addr.isMappedIPv4(); }); luaCtx.registerFunction("mapToIPv4", [](const ComboAddress& addr) { return addr.mapToIPv4(); }); - luaCtx.registerFunction("match", [](nmts_t& set, const ComboAddress& addr) { return set.match(addr); }); +#ifndef DISABLE_DYNBLOCKS + luaCtx.registerFunction("match", [](const ClientAddressDynamicRules& set, const ComboAddress& addr) { return set.match(addr); }); +#endif /* DISABLE_DYNBLOCKS */ #endif /* DISABLE_COMBO_ADDR_BINDINGS */ #ifndef DISABLE_DNSNAME_BINDINGS diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 28489057d6ea..e9823c066e2e 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -21,6 +21,7 @@ */ #include "dnsdist-async.hh" +#include "dnsdist-cache.hh" #include "dnsdist-dnsparser.hh" #include "dnsdist-dynblocks.hh" #include "dnsdist-ecs.hh" diff --git a/pdns/dnsdistdist/dnsdist-lua.cc b/pdns/dnsdistdist/dnsdist-lua.cc index d62ab765ebc9..25b844e6fd24 100644 --- a/pdns/dnsdistdist/dnsdist-lua.cc +++ b/pdns/dnsdistdist/dnsdist-lua.cc @@ -38,12 +38,14 @@ #include "dnsdist.hh" #include "dnsdist-backend.hh" +#include "dnsdist-cache.hh" #include "dnsdist-carbon.hh" #include "dnsdist-concurrent-connections.hh" #include "dnsdist-configuration.hh" #include "dnsdist-console.hh" #include "dnsdist-crypto.hh" #include "dnsdist-dynblocks.hh" +#include "dnsdist-dynbpf.hh" #include "dnsdist-discovery.hh" #include "dnsdist-ecs.hh" #include "dnsdist-frontend.hh" diff --git a/pdns/dnsdistdist/dnsdist-lua.hh b/pdns/dnsdistdist/dnsdist-lua.hh index dd5ee053a9f3..cc2c83c74f78 100644 --- a/pdns/dnsdistdist/dnsdist-lua.hh +++ b/pdns/dnsdistdist/dnsdist-lua.hh @@ -162,7 +162,6 @@ template using LuaTypeOrArrayOf = boost::variant>; using luaruleparams_t = LuaAssociativeTable; -using nmts_t = NetmaskTree; using luadnsrule_t = boost::variant, std::shared_ptr, DNSName, LuaArray>; std::shared_ptr makeRule(const luadnsrule_t& var, const std::string& calledFrom); diff --git a/pdns/dnsdistdist/dnsdist-web.cc b/pdns/dnsdistdist/dnsdist-web.cc index a9e4afc2efb4..7790e755f0d3 100644 --- a/pdns/dnsdistdist/dnsdist-web.cc +++ b/pdns/dnsdistdist/dnsdist-web.cc @@ -32,8 +32,10 @@ #include "base64.hh" #include "connection-management.hh" #include "dnsdist.hh" +#include "dnsdist-cache.hh" #include "dnsdist-configuration.hh" #include "dnsdist-dynblocks.hh" +#include "dnsdist-dynbpf.hh" #include "dnsdist-frontend.hh" #include "dnsdist-healthchecks.hh" #include "dnsdist-metrics.hh" diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index 0e1db2182c3f..c33f6e5426d9 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -96,7 +96,6 @@ using std::thread; string g_outputBuffer; shared_ptr g_defaultBPFFilter{nullptr}; -std::vector> g_dynBPFFilters; /* UDP: the grand design. Per socket we listen on for incoming queries there is one thread. Then we have a bunch of connected sockets for talking to downstream servers. diff --git a/pdns/dnsdistdist/dnsdist.hh b/pdns/dnsdistdist/dnsdist.hh index 7f236f9d6284..ca2a710f7265 100644 --- a/pdns/dnsdistdist/dnsdist.hh +++ b/pdns/dnsdistdist/dnsdist.hh @@ -33,12 +33,8 @@ #include #include -#include - +#include "bpf-filter.hh" #include "circular_buffer.hh" -#include "dnscrypt.hh" -#include "dnsdist-cache.hh" -#include "dnsdist-dynbpf.hh" #include "dnsdist-idstate.hh" #include "dnsdist-lbpolicies.hh" #include "dnsdist-protocols.hh" @@ -51,7 +47,6 @@ #include "misc.hh" #include "mplexer.hh" #include "noinitvector.hh" -#include "tcpiohandler.hh" #include "uuid-utils.hh" #include "proxy-protocol.hh" #include "stat_t.hh" @@ -202,73 +197,6 @@ struct DNSResponse : DNSQuestion const std::shared_ptr& d_downstream; }; -struct DynBlock -{ - DynBlock() - { - 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_) - { - } - - DynBlock(const DynBlock& rhs) : - reason(rhs.reason), domain(rhs.domain), until(rhs.until), tagSettings(rhs.tagSettings), 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), tagSettings(std::move(rhs.tagSettings)), action(rhs.action), warning(rhs.warning), bpf(rhs.bpf) - { - blocks.store(rhs.blocks); - } - - DynBlock& operator=(const DynBlock& rhs) - { - reason = rhs.reason; - until = rhs.until; - domain = rhs.domain; - action = rhs.action; - blocks.store(rhs.blocks); - warning = rhs.warning; - bpf = rhs.bpf; - tagSettings = rhs.tagSettings; - return *this; - } - - DynBlock& operator=(DynBlock&& rhs) - { - reason = std::move(rhs.reason); - until = rhs.until; - domain = std::move(rhs.domain); - action = rhs.action; - blocks.store(rhs.blocks); - warning = rhs.warning; - bpf = rhs.bpf; - tagSettings = std::move(rhs.tagSettings); - return *this; - } - - struct TagSettings - { - std::string d_name; - std::string d_value; - }; - - string reason; - DNSName domain; - timespec until{}; - std::shared_ptr tagSettings{nullptr}; - mutable std::atomic blocks{0}; - DNSAction::Action action{DNSAction::Action::None}; - bool warning{false}; - bool bpf{false}; -}; - using pdns::stat_t; class BasicQPSLimiter @@ -387,6 +315,8 @@ class XskPacket; class XskSocket; class XskWorker; +class DNSCryptContext; + struct ClientState { ClientState(const ComboAddress& local_, bool isTCP_, bool doReusePort, int fastOpenQueue, const std::string& itfName, const std::set& cpus_, bool enableProxyProtocol) : @@ -586,6 +516,7 @@ struct ClientState }; struct CrossProtocolQuery; +class FDMultiplexer; struct DownstreamState : public std::enable_shared_from_this { @@ -961,6 +892,8 @@ void responderThread(std::shared_ptr dss); extern RecursiveLockGuarded g_lua; extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex +class DNSDistPacketCache; + class DNSRule { public: @@ -1016,7 +949,6 @@ enum ednsHeaderFlags }; extern shared_ptr g_defaultBPFFilter; -extern std::vector> g_dynBPFFilters; void tcpAcceptorThread(const std::vector& states); @@ -1029,6 +961,8 @@ bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, bool checkQueryHeaders(const struct dnsheader& dnsHeader, ClientState& clientState); +class DNSCryptQuery; + bool handleDNSCryptQuery(PacketBuffer& packet, DNSCryptQuery& query, bool tcp, time_t now, PacketBuffer& response); bool checkDNSCryptQuery(const ClientState& clientState, PacketBuffer& query, std::unique_ptr& dnsCryptQuery, time_t now, bool tcp); @@ -1040,6 +974,7 @@ enum class ProcessQueryResult : uint8_t Asynchronous }; +#include "dnsdist-actions.hh" #include "dnsdist-rule-chains.hh" ProcessQueryResult processQuery(DNSQuestion& dnsQuestion, std::shared_ptr& selectedBackend); diff --git a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc index c53009705126..33e8140ee2f2 100644 --- a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc @@ -28,6 +28,8 @@ #include #include "dnsdist-lua-ffi.hh" +#include "dnsdist-cache.hh" +#include "dnsdist-configuration.hh" #include "dnsdist-rings.hh" #include "dnsdist-web.hh" #include "dnsparser.hh"