--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stdexcept>
+
+#include "dnsdist-configuration-yaml.hh"
+
+#if defined(HAVE_YAML_CONFIGURATION)
+#include "base64.hh"
+#include "dolog.hh"
+#include "dnsdist-actions-factory.hh"
+#include "dnsdist-backend.hh"
+#include "dnsdist-cache.hh"
+#include "dnsdist-discovery.hh"
+#include "dnsdist-dnsparser.hh"
+#include "dnsdist-dynblocks.hh"
+#include "dnsdist-rules.hh"
+#include "dnsdist-rules-factory.hh"
+#include "dnsdist-kvs.hh"
+#include "dnsdist-web.hh"
+#include "doh.hh"
+#include "fstrm_logger.hh"
+#include "iputils.hh"
+#include "remote_logger.hh"
+
+#include "rust/cxx.h"
+#include "rust/lib.rs.h"
+#include "dnsdist-configuration-yaml-internal.hh"
+
+#include <boost/uuid/string_generator.hpp>
+#endif /* HAVE_YAML_CONFIGURATION */
+
+namespace dnsdist::configuration::yaml
+{
+#if defined(HAVE_YAML_CONFIGURATION)
+
+using RegisteredTypes = std::variant<std::shared_ptr<DNSDistPacketCache>, std::shared_ptr<dnsdist::rust::settings::DNSSelector>, std::shared_ptr<dnsdist::rust::settings::DNSActionWrapper>, std::shared_ptr<dnsdist::rust::settings::DNSResponseActionWrapper>, std::shared_ptr<NetmaskGroup>, std::shared_ptr<KeyValueStore>, std::shared_ptr<KeyValueLookupKey>, std::shared_ptr<RemoteLoggerInterface>, std::shared_ptr<ServerPolicy>>;
+static LockGuarded<std::unordered_map<std::string, RegisteredTypes>> s_registeredTypesMap;
+static std::atomic<bool> s_inConfigCheckMode;
+static std::atomic<bool> s_inClientMode;
+
+template <class T>
+static void registerType(const std::shared_ptr<T>& entry, const ::rust::string& rustName)
+{
+ std::string name(rustName);
+ if (name.empty()) {
+ auto uuid = getUniqueID();
+ name = boost::uuids::to_string(uuid);
+ }
+
+ auto [it, inserted] = s_registeredTypesMap.lock()->try_emplace(name, entry);
+ if (!inserted) {
+ throw std::runtime_error("Trying to register a type named '" + name + "' while one already exists");
+ }
+}
+
+template <class T>
+static std::shared_ptr<T> getRegisteredTypeByName(const std::string& name)
+{
+ auto map = s_registeredTypesMap.lock();
+ auto item = map->find(name);
+ if (item == map->end()) {
+ return nullptr;
+ }
+ if (auto* ptr = std::get_if<std::shared_ptr<T>>(&item->second)) {
+ return *ptr;
+ }
+ return nullptr;
+}
+
+template <class T>
+static std::shared_ptr<T> getRegisteredTypeByName(const ::rust::String& name)
+{
+ auto nameStr = std::string(name);
+ return getRegisteredTypeByName<T>(nameStr);
+}
+
+template <class T>
+static T checkedConversionFromStr(const std::string& context, const std::string& parameterName, const std::string& str)
+{
+ try {
+ return pdns::checked_stoi<T>(std::string(str));
+ }
+ catch (const std::exception& exp) {
+ throw std::runtime_error("Error converting value '" + str + "' for parameter '" + parameterName + "' in YAML directive '" + context + "': " + exp.what());
+ }
+}
+
+template <class T>
+static T checkedConversionFromStr(const std::string& context, const std::string& parameterName, const ::rust::string& str)
+{
+ return checkedConversionFromStr<T>(context, parameterName, std::string(str));
+}
+
+static std::set<int> getCPUPiningFromStr(const std::string& context, const std::string& cpuStr)
+{
+ std::set<int> cpus;
+ std::vector<std::string> tokens;
+ stringtok(tokens, cpuStr);
+ for (const auto& token : tokens) {
+ cpus.insert(checkedConversionFromStr<int>(context, "cpus", token));
+ }
+ return cpus;
+}
+
+static TLSConfig getTLSConfigFromRustIncomingTLS(const dnsdist::rust::settings::IncomingTlsConfiguration& incomingTLSConfig)
+{
+ TLSConfig out;
+ for (const auto& certConfig : incomingTLSConfig.certificates) {
+ TLSCertKeyPair pair(std::string(certConfig.certificate));
+ if (!certConfig.key.empty()) {
+ pair.d_key = std::string(certConfig.key);
+ }
+ if (!certConfig.password.empty()) {
+ pair.d_password = std::string(certConfig.password);
+ }
+ out.d_certKeyPairs.push_back(std::move(pair));
+ }
+ for (const auto& ocspFile : incomingTLSConfig.ocsp_response_files) {
+ out.d_ocspFiles.emplace_back(ocspFile);
+ }
+ out.d_ciphers = std::string(incomingTLSConfig.ciphers);
+ out.d_ciphers13 = std::string(incomingTLSConfig.ciphers_tls_13);
+ out.d_minTLSVersion = libssl_tls_version_from_string(std::string(incomingTLSConfig.minimum_version));
+ out.d_ticketKeyFile = std::string(incomingTLSConfig.ticket_key_file);
+ out.d_keyLogFile = std::string(incomingTLSConfig.key_log_file);
+ out.d_maxStoredSessions = incomingTLSConfig.number_of_stored_sessions;
+ out.d_sessionTimeout = incomingTLSConfig.session_timeout;
+ out.d_ticketsKeyRotationDelay = incomingTLSConfig.tickets_keys_rotation_delay;
+ out.d_numberOfTicketsKeys = incomingTLSConfig.number_of_tickets_keys;
+ out.d_preferServerCiphers = incomingTLSConfig.prefer_server_ciphers;
+ out.d_enableTickets = incomingTLSConfig.session_tickets;
+ out.d_releaseBuffers = incomingTLSConfig.release_buffers;
+ out.d_enableRenegotiation = incomingTLSConfig.enable_renegotiation;
+ out.d_asyncMode = incomingTLSConfig.async_mode;
+ out.d_ktls = incomingTLSConfig.ktls;
+ out.d_readAhead = incomingTLSConfig.read_ahead;
+ return out;
+}
+
+static bool validateTLSConfiguration(const dnsdist::rust::settings::BindConfiguration& bind, const TLSConfig& tlsConfig)
+{
+ if (!bind.tls.ignore_configuration_errors) {
+ return true;
+ }
+
+ // we are asked to try to load the certificates so we can return a potential error
+ // and properly ignore the frontend before actually launching it
+ try {
+ std::map<int, std::string> ocspResponses = {};
+ auto ctx = libssl_init_server_context(tlsConfig, ocspResponses);
+ }
+ catch (const std::runtime_error& e) {
+ errlog("Ignoring %s frontend: '%s'", bind.protocol, e.what());
+ return false;
+ }
+
+ return true;
+}
+
+static bool handleTLSConfiguration(const dnsdist::rust::settings::BindConfiguration& bind, ClientState& state)
+{
+ auto tlsConfig = getTLSConfigFromRustIncomingTLS(bind.tls);
+ if (!validateTLSConfiguration(bind, tlsConfig)) {
+ return false;
+ }
+
+ auto protocol = boost::to_lower_copy(std::string(bind.protocol));
+ if (protocol == "dot") {
+ auto frontend = std::make_shared<TLSFrontend>(TLSFrontend::ALPN::DoT);
+ frontend->d_provider = std::string(bind.tls.provider);
+ boost::algorithm::to_lower(frontend->d_provider);
+ frontend->d_proxyProtocolOutsideTLS = bind.tls.proxy_protocol_outside_tls;
+ frontend->d_tlsConfig = std::move(tlsConfig);
+ state.tlsFrontend = std::move(frontend);
+ }
+ else if (protocol == "doq") {
+ auto frontend = std::make_shared<DOQFrontend>();
+ frontend->d_local = ComboAddress(std::string(bind.listen_address), 853);
+ frontend->d_quicheParams.d_tlsConfig = std::move(tlsConfig);
+ frontend->d_quicheParams.d_maxInFlight = bind.doq.max_concurrent_queries_per_connection;
+ frontend->d_quicheParams.d_idleTimeout = bind.quic.idle_timeout;
+ frontend->d_quicheParams.d_keyLogFile = std::string(bind.tls.key_log_file);
+ if (dnsdist::doq::s_available_cc_algorithms.count(std::string(bind.quic.congestion_control_algorithm)) > 0) {
+ frontend->d_quicheParams.d_ccAlgo = std::string(bind.quic.congestion_control_algorithm);
+ }
+ frontend->d_internalPipeBufferSize = bind.quic.internal_pipe_buffer_size;
+ state.doqFrontend = std::move(frontend);
+ }
+ else if (protocol == "doh3") {
+ auto frontend = std::make_shared<DOH3Frontend>();
+ frontend->d_local = ComboAddress(std::string(bind.listen_address), 443);
+ frontend->d_quicheParams.d_tlsConfig = std::move(tlsConfig);
+ frontend->d_quicheParams.d_idleTimeout = bind.quic.idle_timeout;
+ frontend->d_quicheParams.d_keyLogFile = std::string(bind.tls.key_log_file);
+ if (dnsdist::doq::s_available_cc_algorithms.count(std::string(bind.quic.congestion_control_algorithm)) > 0) {
+ frontend->d_quicheParams.d_ccAlgo = std::string(bind.quic.congestion_control_algorithm);
+ }
+ frontend->d_internalPipeBufferSize = bind.quic.internal_pipe_buffer_size;
+ state.doh3Frontend = std::move(frontend);
+ }
+ else if (protocol == "doh") {
+ auto frontend = std::make_shared<DOHFrontend>();
+ frontend->d_tlsContext.d_provider = std::string(bind.tls.provider);
+ boost::algorithm::to_lower(frontend->d_tlsContext.d_provider);
+ frontend->d_library = std::string(bind.doh.provider);
+ if (frontend->d_library == "h2o") {
+#ifdef HAVE_LIBH2OEVLOOP
+ frontend = std::make_shared<H2ODOHFrontend>();
+ // we _really_ need to set it again, as we just replaced the generic frontend by a new one
+ frontend->d_library = "h2o";
+#else /* HAVE_LIBH2OEVLOOP */
+ errlog("DOH bind %s is configured to use libh2o but the library is not available", bind.listen_address);
+ return false;
+#endif /* HAVE_LIBH2OEVLOOP */
+ }
+ else if (frontend->d_library == "nghttp2") {
+#ifndef HAVE_NGHTTP2
+ errlog("DOH bind %s is configured to use nghttp2 but the library is not available", bind.listen_address);
+ return false;
+#endif /* HAVE_NGHTTP2 */
+ }
+ else {
+ errlog("DOH bind %s is configured to use an unknown library ('%s')", bind.listen_address, frontend->d_library);
+ return false;
+ }
+
+ for (const auto& path : bind.doh.paths) {
+ frontend->d_urls.emplace(path);
+ }
+ frontend->d_idleTimeout = bind.doh.idle_timeout;
+ frontend->d_serverTokens = std::string(bind.doh.server_tokens);
+ frontend->d_sendCacheControlHeaders = bind.doh.send_cache_control_headers;
+ frontend->d_keepIncomingHeaders = bind.doh.keep_incoming_headers;
+ frontend->d_trustForwardedForHeader = bind.doh.trust_forwarded_for_header;
+ frontend->d_earlyACLDrop = bind.doh.early_acl_drop;
+ frontend->d_internalPipeBufferSize = bind.doh.internal_pipe_buffer_size;
+ frontend->d_exactPathMatching = bind.doh.exact_path_matching;
+ for (const auto& customHeader : bind.doh.custom_response_headers) {
+ auto headerResponse = std::pair(boost::to_lower_copy(std::string(customHeader.key)), std::string(customHeader.value));
+ frontend->d_customResponseHeaders.insert(std::move(headerResponse));
+ }
+
+ if (!bind.doh.responses_map.empty()) {
+ auto newMap = std::make_shared<std::vector<std::shared_ptr<DOHResponseMapEntry>>>();
+ for (const auto& responsesMap : bind.doh.responses_map) {
+ boost::optional<std::unordered_map<std::string, std::string>> headers;
+ if (!responsesMap.headers.empty()) {
+ headers = std::unordered_map<std::string, std::string>();
+ for (const auto& header : responsesMap.headers) {
+ headers->emplace(boost::to_lower_copy(std::string(header.key)), std::string(header.value));
+ }
+ }
+ auto entry = std::make_shared<DOHResponseMapEntry>(std::string(responsesMap.expression), responsesMap.status, PacketBuffer(responsesMap.content.begin(), responsesMap.content.end()), headers);
+ newMap->emplace_back(std::move(entry));
+ }
+ frontend->d_responsesMap = std::move(newMap);
+ }
+
+ if (!tlsConfig.d_certKeyPairs.empty()) {
+ frontend->d_tlsContext.d_addr = ComboAddress(std::string(bind.listen_address), 443);
+ infolog("DNS over HTTPS configured");
+ }
+ else {
+ frontend->d_tlsContext.d_addr = ComboAddress(std::string(bind.listen_address), 80);
+ infolog("No certificate provided for DoH endpoint %s, running in DNS over HTTP mode instead of DNS over HTTPS", frontend->d_tlsContext.d_addr.toStringWithPort());
+ }
+
+ frontend->d_tlsContext.d_proxyProtocolOutsideTLS = bind.tls.proxy_protocol_outside_tls;
+ frontend->d_tlsContext.d_tlsConfig = std::move(tlsConfig);
+ state.dohFrontend = std::move(frontend);
+ }
+ else if (protocol != "do53") {
+ errlog("Bind %s is configured to use an unknown protocol ('%s')", bind.listen_address, protocol);
+ return false;
+ }
+
+ return true;
+}
+
+template <class T>
+static bool getOptionalLuaFunction(T& destination, const ::rust::string& functionName)
+{
+ auto lua = g_lua.lock();
+ auto function = lua->readVariable<boost::optional<T>>(std::string(functionName));
+ if (!function) {
+ return false;
+ }
+ destination = *function;
+ return true;
+}
+
+static std::shared_ptr<DownstreamState> createBackendFromConfiguration(const dnsdist::rust::settings::BackendConfiguration& config, bool configCheck)
+{
+ DownstreamState::Config backendConfig;
+ std::shared_ptr<TLSCtx> tlsCtx;
+
+ backendConfig.d_numberOfSockets = config.sockets;
+ backendConfig.d_qpsLimit = config.queries_per_second;
+ backendConfig.order = config.order;
+ backendConfig.d_weight = config.weight;
+ backendConfig.d_retries = config.retries;
+ backendConfig.d_maxInFlightQueriesPerConn = config.max_in_flight;
+ backendConfig.d_tcpConcurrentConnectionsLimit = config.max_concurrent_tcp_connections;
+ backendConfig.name = std::string(config.name);
+ if (!config.id.empty()) {
+ backendConfig.id = boost::uuids::string_generator()(std::string(config.id));
+ }
+ backendConfig.useECS = config.use_client_subnet;
+ backendConfig.useProxyProtocol = config.use_proxy_protocol;
+ backendConfig.d_proxyProtocolAdvertiseTLS = config.proxy_protocol_advertise_tls;
+ backendConfig.disableZeroScope = config.disable_zero_scope;
+ backendConfig.ipBindAddrNoPort = config.ip_bind_addr_no_port;
+ backendConfig.reconnectOnUp = config.reconnect_on_up;
+ backendConfig.d_cpus = getCPUPiningFromStr("backend", std::string(config.cpus));
+ backendConfig.d_tcpOnly = config.tcp_only;
+
+ backendConfig.tcpConnectTimeout = config.tcp.connect_timeout;
+ backendConfig.tcpSendTimeout = config.tcp.send_timeout;
+ backendConfig.tcpRecvTimeout = config.tcp.receive_timeout;
+ backendConfig.tcpFastOpen = config.tcp.fast_open;
+
+ const auto& hcConf = config.health_checks;
+ backendConfig.checkInterval = hcConf.interval;
+ if (!hcConf.qname.empty()) {
+ backendConfig.checkName = DNSName(std::string(hcConf.qname));
+ }
+ backendConfig.checkType = std::string(hcConf.qtype);
+ if (!hcConf.qclass.empty()) {
+ backendConfig.checkClass = QClass(std::string(hcConf.qclass));
+ }
+ backendConfig.checkTimeout = hcConf.timeout;
+ backendConfig.d_tcpCheck = hcConf.use_tcp;
+ backendConfig.setCD = hcConf.set_cd;
+ backendConfig.mustResolve = hcConf.must_resolve;
+ backendConfig.maxCheckFailures = hcConf.max_failures;
+ backendConfig.minRiseSuccesses = hcConf.rise;
+
+ getOptionalLuaFunction<DownstreamState::checkfunc_t>(backendConfig.checkFunction, hcConf.function);
+
+ auto availability = DownstreamState::getAvailabilityFromStr(std::string(hcConf.mode));
+ if (availability) {
+ backendConfig.availability = *availability;
+ }
+
+ backendConfig.d_lazyHealthCheckSampleSize = hcConf.lazy.sample_size;
+ backendConfig.d_lazyHealthCheckMinSampleCount = hcConf.lazy.min_sample_count;
+ backendConfig.d_lazyHealthCheckThreshold = hcConf.lazy.threshold;
+ backendConfig.d_lazyHealthCheckFailedInterval = hcConf.lazy.interval;
+ backendConfig.d_lazyHealthCheckUseExponentialBackOff = hcConf.lazy.use_exponential_back_off;
+ backendConfig.d_lazyHealthCheckMaxBackOff = hcConf.lazy.max_back_off;
+ if (hcConf.lazy.mode == "TimeoutOnly") {
+ backendConfig.d_lazyHealthCheckMode = DownstreamState::LazyHealthCheckMode::TimeoutOnly;
+ }
+ else if (hcConf.lazy.mode == "TimeoutOrServFail") {
+ backendConfig.d_lazyHealthCheckMode = DownstreamState::LazyHealthCheckMode::TimeoutOrServFail;
+ }
+ else if (!hcConf.lazy.mode.empty()) {
+ warnlog("Ignoring unknown value '%s' for 'lazy.mode' on backend %s", hcConf.lazy.mode, std::string(config.address));
+ }
+
+ backendConfig.d_upgradeToLazyHealthChecks = config.auto_upgrade.use_lazy_health_check;
+
+ uint16_t serverPort = 53;
+ const auto& tlsConf = config.tls;
+ auto protocol = boost::to_lower_copy(std::string(config.protocol));
+ if (protocol == "dot" || protocol == "doh") {
+ backendConfig.d_tlsParams.d_provider = std::string(tlsConf.provider);
+ backendConfig.d_tlsParams.d_ciphers = std::string(tlsConf.ciphers);
+ backendConfig.d_tlsParams.d_ciphers13 = std::string(tlsConf.ciphers_tls_13);
+ backendConfig.d_tlsParams.d_caStore = std::string(tlsConf.ca_store);
+ backendConfig.d_tlsParams.d_keyLogFile = std::string(tlsConf.key_log_file);
+ backendConfig.d_tlsParams.d_validateCertificates = tlsConf.validate_certificate;
+ backendConfig.d_tlsParams.d_releaseBuffers = tlsConf.release_buffers;
+ backendConfig.d_tlsParams.d_enableRenegotiation = tlsConf.enable_renegotiation;
+ backendConfig.d_tlsParams.d_ktls = tlsConf.ktls;
+ backendConfig.d_tlsSubjectName = std::string(tlsConf.subject_name);
+ if (!tlsConf.subject_address.empty()) {
+ try {
+ ComboAddress addr{std::string(tlsConf.subject_address)};
+ backendConfig.d_tlsSubjectName = addr.toString();
+ backendConfig.d_tlsSubjectIsAddr = true;
+ }
+ catch (const std::exception&) {
+ errlog("Error creating new server: downstream subject_address value must be a valid IP address");
+ }
+ }
+ }
+
+ if (protocol == "dot") {
+ serverPort = 853;
+ backendConfig.d_tlsParams.d_alpn = TLSFrontend::ALPN::DoT;
+ }
+ else if (protocol == "doh") {
+ serverPort = 443;
+ backendConfig.d_tlsParams.d_alpn = TLSFrontend::ALPN::DoH;
+ backendConfig.d_dohPath = std::string(config.doh.path);
+ backendConfig.d_addXForwardedHeaders = config.doh.add_x_forwarded_headers;
+ }
+
+ for (const auto& pool : config.pools) {
+ backendConfig.pools.emplace(pool);
+ }
+
+ backendConfig.remote = ComboAddress(std::string(config.address), serverPort);
+
+#warning handle XSK
+
+ if (protocol == "dot" || protocol == "doh") {
+ tlsCtx = getTLSContext(backendConfig.d_tlsParams);
+ }
+
+ auto downstream = std::make_shared<DownstreamState>(std::move(backendConfig), std::move(tlsCtx), !configCheck);
+
+ const auto& autoUpgradeConf = config.auto_upgrade;
+ if (autoUpgradeConf.enabled && downstream->getProtocol() != dnsdist::Protocol::DoT && downstream->getProtocol() != dnsdist::Protocol::DoH) {
+ dnsdist::ServiceDiscovery::addUpgradeableServer(downstream, autoUpgradeConf.interval, std::string(autoUpgradeConf.pool), autoUpgradeConf.doh_key, autoUpgradeConf.keep);
+ }
+
+ return downstream;
+}
+#endif /* defined(HAVE_YAML_CONFIGURATION) */
+
+bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool configCheck)
+{
+#if defined(HAVE_YAML_CONFIGURATION)
+ // this is not very elegant but passing a context to the functions called by the
+ // Rust code would be quite cumbersome so for now let's settle for this
+ s_inConfigCheckMode.store(configCheck);
+ s_inClientMode.store(isClient);
+
+ auto file = std::ifstream(fileName);
+ if (!file.is_open()) {
+ errlog("Unable to open YAML file %s: %s", fileName, stringerror(errno));
+ return false;
+ }
+
+ /* register built-in policies */
+ for (const auto& policy : dnsdist::lbpolicies::getBuiltInPolicies()) {
+ registerType<ServerPolicy>(policy, ::rust::string(policy->d_name));
+ }
+
+ try {
+ auto data = std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
+
+ auto globalConfig = dnsdist::rust::settings::from_yaml_string(data);
+
+ if (!globalConfig.console.listen_address.empty()) {
+ const auto& consoleConf = globalConfig.console;
+ dnsdist::configuration::updateRuntimeConfiguration([consoleConf](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_consoleServerAddress = ComboAddress(std::string(consoleConf.listen_address), 5199);
+ config.d_consoleEnabled = true;
+ config.d_consoleACL.clear();
+ for (const auto& aclEntry : consoleConf.acl) {
+ config.d_consoleACL.addMask(std::string(aclEntry));
+ }
+ B64Decode(std::string(consoleConf.key), config.d_consoleKey);
+ });
+ }
+
+ if (isClient) {
+ return true;
+ }
+
+ if (!globalConfig.acl.empty()) {
+ dnsdist::configuration::updateRuntimeConfiguration([&acl = globalConfig.acl](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_ACL.clear();
+ for (const auto& aclEntry : acl) {
+ config.d_ACL.addMask(std::string(aclEntry));
+ }
+ });
+ }
+
+ for (const auto& bind : globalConfig.binds) {
+ ComboAddress listeningAddress(std::string(bind.listen_address), 53);
+ updateImmutableConfiguration([&bind, listeningAddress](ImmutableConfiguration& config) {
+ auto protocol = boost::to_lower_copy(std::string(bind.protocol));
+ auto cpus = getCPUPiningFromStr("binds", std::string(bind.cpus));
+ for (size_t idx = 0; idx < bind.threads; idx++) {
+ auto state = std::make_shared<ClientState>(listeningAddress, protocol != "doq" && protocol != "doh3", bind.reuseport, bind.tcp.fast_open_queue_size, std::string(bind.interface), cpus, false);
+ if (bind.tcp.listen_queue_size > 0) {
+ state->tcpListenQueueSize = bind.tcp.listen_queue_size;
+ }
+ if (bind.tcp.max_in_flight_queries > 0) {
+ state->d_maxInFlightQueriesPerConn = bind.tcp.max_in_flight_queries;
+ }
+ if (bind.tcp.max_concurrent_connections > 0) {
+ state->d_tcpConcurrentConnectionsLimit = bind.tcp.max_concurrent_connections;
+ }
+
+ for (const auto& addr : bind.additional_addresses) {
+ try {
+ ComboAddress address{std::string(addr)};
+ state->d_additionalAddresses.emplace_back(address, -1);
+ }
+ catch (const PDNSException& e) {
+ errlog("Unable to parse additional address %s for %s bind: %s", std::string(addr), protocol, e.reason);
+ }
+ }
+
+ if (protocol != "do53") {
+ if (!handleTLSConfiguration(bind, *state)) {
+ continue;
+ }
+ }
+
+ config.d_frontends.emplace_back(std::move(state));
+ if (protocol == "do53") {
+ /* also create the UDP listener */
+ state = std::make_shared<ClientState>(ComboAddress(std::string(bind.listen_address), 53), false, bind.reuseport, bind.tcp.fast_open_queue_size, std::string(bind.interface), cpus, false);
+ config.d_frontends.emplace_back(std::move(state));
+ }
+ }
+ });
+ }
+
+ for (const auto& backend : globalConfig.backends) {
+ auto downstream = createBackendFromConfiguration(backend, configCheck);
+
+ if (!downstream->d_config.pools.empty()) {
+ for (const auto& poolName : downstream->d_config.pools) {
+ addServerToPool(poolName, downstream);
+ }
+ }
+ else {
+ addServerToPool("", downstream);
+ }
+
+ dnsdist::backend::registerNewBackend(downstream);
+ }
+
+ if (!globalConfig.proxy_protocol.acl.empty()) {
+ dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_proxyProtocolACL.clear();
+ for (const auto& aclEntry : globalConfig.proxy_protocol.acl) {
+ config.d_proxyProtocolACL.addMask(std::string(aclEntry));
+ }
+ });
+ }
+
+#ifndef DISABLE_CARBON
+ if (!globalConfig.metrics.carbon.empty()) {
+ dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ for (const auto& carbonConfig : globalConfig.metrics.carbon) {
+ auto newEndpoint = dnsdist::Carbon::newEndpoint(std::string(carbonConfig.address),
+ std::string(carbonConfig.name),
+ carbonConfig.interval,
+ carbonConfig.name_space.empty() ? "dnsdist" : std::string(carbonConfig.name_space),
+ carbonConfig.instance.empty() ? "main" : std::string(carbonConfig.instance));
+ config.d_carbonEndpoints.push_back(std::move(newEndpoint));
+ }
+ });
+ }
+#endif /* DISABLE_CARBON */
+
+ if (!globalConfig.webserver.listen_address.empty()) {
+ const auto& webConfig = globalConfig.webserver;
+ ComboAddress local;
+ try {
+ local = ComboAddress{std::string(webConfig.listen_address)};
+ }
+ catch (const PDNSException& e) {
+ throw std::runtime_error(std::string("Error parsing the bind address for the webserver: ") + e.reason);
+ }
+ dnsdist::configuration::updateRuntimeConfiguration([local, webConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_webServerAddress = local;
+ if (!webConfig.password.empty()) {
+ auto holder = std::make_shared<CredentialsHolder>(std::string(webConfig.password), webConfig.hash_plaintext_credentials);
+ if (!holder->wasHashed() && holder->isHashingAvailable()) {
+ infolog("Passing a plain-text password via the 'webserver.password' parameter to is not advised, please consider generating a hashed one using 'hashPassword()' instead.");
+ }
+ config.d_webPassword = std::move(holder);
+ }
+ if (!webConfig.api_key.empty()) {
+ auto holder = std::make_shared<CredentialsHolder>(std::string(webConfig.api_key), webConfig.hash_plaintext_credentials);
+ if (!holder->wasHashed() && holder->isHashingAvailable()) {
+ infolog("Passing a plain-text API key via the 'webserver.api_key' parameter to is not advised, please consider generating a hashed one using 'hashPassword()' instead.");
+ }
+ config.d_webAPIKey = std::move(holder);
+ }
+ if (!webConfig.acl.empty()) {
+ config.d_webServerACL.clear();
+ for (const auto& acl : webConfig.acl) {
+ config.d_webServerACL.toMasks(std::string(acl));
+ }
+ }
+ if (!webConfig.custom_headers.empty()) {
+ if (!config.d_webCustomHeaders) {
+ config.d_webCustomHeaders = std::unordered_map<std::string, std::string>();
+ for (const auto& customHeader : webConfig.custom_headers) {
+ auto headerResponse = std::pair(boost::to_lower_copy(std::string(customHeader.key)), std::string(customHeader.value));
+ config.d_webCustomHeaders->insert(std::move(headerResponse));
+ }
+ }
+ }
+
+ config.d_apiRequiresAuthentication = webConfig.api_requires_authentication;
+ config.d_dashboardRequiresAuthentication = webConfig.dashboard_requires_authentication;
+ config.d_statsRequireAuthentication = webConfig.stats_require_authentication;
+ dnsdist::webserver::setMaxConcurrentConnections(webConfig.max_concurrent_connections);
+ config.d_apiConfigDirectory = std::string(webConfig.api_configuration_directory);
+ config.d_apiReadWrite = webConfig.api_read_write;
+ });
+ }
+
+ if (globalConfig.query_count.enabled) {
+ dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_queryCountConfig.d_enabled = true;
+ if (!globalConfig.query_count.filter.empty()) {
+ getOptionalLuaFunction<dnsdist::QueryCount::Configuration::Filter>(config.d_queryCountConfig.d_filter, globalConfig.query_count.filter);
+ }
+ });
+ }
+
+ if (!globalConfig.dynamic_rules_settings.default_action.empty()) {
+ dnsdist::configuration::updateRuntimeConfiguration([default_action = globalConfig.dynamic_rules_settings.default_action](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_dynBlockAction = DNSAction::typeFromString(std::string(default_action));
+ });
+ }
+
+ for (const auto& dbrg : globalConfig.dynamic_rules) {
+ auto dbrgObj = std::make_shared<DynBlockRulesGroup>();
+ dbrgObj->setMasks(dbrg.mask_ipv4, dbrg.mask_ipv6, dbrg.mask_port);
+ for (const auto& range : dbrg.exclude_ranges) {
+ dbrgObj->excludeRange(Netmask(std::string(range)));
+ }
+ for (const auto& range : dbrg.include_ranges) {
+ dbrgObj->includeRange(Netmask(std::string(range)));
+ }
+ for (const auto& domain : dbrg.exclude_domains) {
+ dbrgObj->excludeDomain(DNSName(std::string(domain)));
+ }
+ for (const auto& rule : dbrg.rules) {
+ if (rule.rule_type == "query-rate") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, rule.rate, rule.warning_rate, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setQueryRate(std::move(ruleParams));
+ }
+ else if (rule.rule_type == "rcode-rate") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, rule.rate, rule.warning_rate, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setRCodeRate(checkedConversionFromStr<int>("dynamic-rules.rules.rcode_rate", "rcode", rule.rcode), std::move(ruleParams));
+ }
+ else if (rule.rule_type == "rcode-ratio") {
+ DynBlockRulesGroup::DynBlockRatioRule ruleParams(std::string(rule.comment), rule.action_duration, rule.ratio, rule.warning_ratio, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)), rule.minimum_number_of_responses);
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setRCodeRatio(checkedConversionFromStr<int>("dynamic-rules.rules.rcode_ratio", "rcode", rule.rcode), std::move(ruleParams));
+ }
+ else if (rule.rule_type == "qtype-rate") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, rule.rate, rule.warning_rate, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setRCodeRate(checkedConversionFromStr<int>("dynamic-rules.rules.qtype_rate", "qtype", rule.qtype), std::move(ruleParams));
+ }
+ else if (rule.rule_type == "qtype-ratio") {
+ DynBlockRulesGroup::DynBlockRatioRule ruleParams(std::string(rule.comment), rule.action_duration, rule.ratio, rule.warning_ratio, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)), rule.minimum_number_of_responses);
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setRCodeRatio(checkedConversionFromStr<int>("dynamic-rules.rules.qtype_ratio", "qtype", rule.qtype), std::move(ruleParams));
+ }
+ else if (rule.rule_type == "cache-miss-ratio") {
+ DynBlockRulesGroup::DynBlockCacheMissRatioRule ruleParams(std::string(rule.comment), rule.action_duration, rule.ratio, rule.warning_ratio, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)), rule.minimum_number_of_responses, rule.minimum_global_cache_hit_ratio);
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setCacheMissRatio(std::move(ruleParams));
+ }
+ else if (rule.rule_type == "response-byte-rate") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, rule.rate, rule.warning_rate, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dbrgObj->setResponseByteRate(std::move(ruleParams));
+ }
+ else if (rule.rule_type == "suffix-match") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, 0, 0, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ DynBlockRulesGroup::smtVisitor_t visitor;
+ getOptionalLuaFunction<DynBlockRulesGroup::smtVisitor_t>(visitor, rule.visitor_function);
+ dbrgObj->setSuffixMatchRule(std::move(ruleParams), std::move(visitor));
+ }
+ else if (rule.rule_type == "suffix-match-ffi") {
+ DynBlockRulesGroup::DynBlockRule ruleParams(std::string(rule.comment), rule.action_duration, 0, 0, rule.seconds, rule.action.empty() ? DNSAction::Action::None : DNSAction::typeFromString(std::string(rule.action)));
+ if (ruleParams.d_action == DNSAction::Action::SetTag && !rule.tag_name.empty()) {
+ ruleParams.d_tagSettings = std::make_shared<DynBlock::TagSettings>();
+ ruleParams.d_tagSettings->d_name = std::string(rule.tag_name);
+ ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
+ }
+ dnsdist_ffi_stat_node_visitor_t visitor;
+ getOptionalLuaFunction<dnsdist_ffi_stat_node_visitor_t>(visitor, rule.visitor_function);
+ dbrgObj->setSuffixMatchRuleFFI(std::move(ruleParams), std::move(visitor));
+ }
+ }
+ dnsdist::DynamicBlocks::registerGroup(dbrgObj);
+ }
+
+ if (!globalConfig.tuning.tcp.fast_open_key.empty()) {
+ std::vector<uint32_t> key(4);
+ auto ret = sscanf(globalConfig.tuning.tcp.fast_open_key.c_str(), "%" SCNx32 "-%" SCNx32 "-%" SCNx32 "-%" SCNx32, &key.at(0), &key.at(1), &key.at(2), &key.at(3));
+ if (ret < 0 || static_cast<size_t>(ret) != key.size()) {
+ throw std::runtime_error("Invalid value passed to tuning.tcp.fast_open_key!\n");
+ }
+ dnsdist::configuration::updateImmutableConfiguration([&key](dnsdist::configuration::ImmutableConfiguration& config) {
+ config.d_tcpFastOpenKey = std::move(key);
+ });
+ }
+
+ if (!globalConfig.general.capabilities_to_retain.empty()) {
+ dnsdist::configuration::updateImmutableConfiguration([capabilities = globalConfig.general.capabilities_to_retain](dnsdist::configuration::ImmutableConfiguration& config) {
+ for (const auto& capability : capabilities) {
+ config.d_capabilitiesToRetain.emplace(std::string(capability));
+ }
+ });
+ }
+
+ for (const auto& cache : globalConfig.packet_caches) {
+ auto packetCacheObj = std::make_shared<DNSDistPacketCache>(cache.size, cache.max_ttl, cache.min_ttl, cache.temporary_failure_ttl, cache.max_negative_ttl, cache.stale_ttl, cache.dont_age, cache.shards, cache.deferrable_insert_lock, cache.parse_ecs);
+
+ packetCacheObj->setKeepStaleData(cache.keep_stale_data);
+ std::unordered_set<uint16_t> optionsToSkip{EDNSOptionCode::COOKIE};
+
+ for (const auto& option : cache.options_to_skip) {
+ optionsToSkip.insert(pdns::checked_stoi<uint16_t>(std::string(option)));
+ }
+
+ if (cache.cookie_hashing) {
+ optionsToSkip.erase(EDNSOptionCode::COOKIE);
+ }
+
+ packetCacheObj->setSkippedOptions(optionsToSkip);
+ if (cache.maximum_entry_size >= sizeof(dnsheader)) {
+ packetCacheObj->setMaximumEntrySize(cache.maximum_entry_size);
+ }
+
+ registerType<DNSDistPacketCache>(packetCacheObj, cache.name);
+ }
+
+ for (const auto& policy : globalConfig.load_balancing_policies.custom_policies) {
+ if (policy.ffi) {
+ if (policy.per_thread) {
+ auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::string(policy.function));
+ registerType<ServerPolicy>(policyObj, policy.name);
+ }
+ else {
+ ServerPolicy::ffipolicyfunc_t function;
+
+ if (!getOptionalLuaFunction<ServerPolicy::ffipolicyfunc_t>(function, policy.function)) {
+ throw std::runtime_error("Custom FFI load-balancing policy '" + std::string(policy.name) + "' is referring to a non-existent Lua function '" + std::string(policy.function) + "'");
+ }
+ auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::move(function));
+ registerType<ServerPolicy>(policyObj, policy.name);
+ }
+ }
+ else {
+ ServerPolicy::policyfunc_t function;
+ if (!getOptionalLuaFunction<ServerPolicy::policyfunc_t>(function, policy.function)) {
+ throw std::runtime_error("Custom load-balancing policy '" + std::string(policy.name) + "' is referring to a non-existent Lua function '" + std::string(policy.function) + "'");
+ }
+ auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::move(function), true);
+ registerType<ServerPolicy>(policyObj, policy.name);
+ }
+ }
+
+ for (const auto& pool : globalConfig.pools) {
+ std::shared_ptr<ServerPool> poolObj = createPoolIfNotExists(std::string(pool.name));
+ if (!pool.packet_cache.empty()) {
+ poolObj->packetCache = getRegisteredTypeByName<DNSDistPacketCache>(pool.packet_cache);
+ }
+ if (!pool.policy.empty()) {
+ poolObj->policy = getRegisteredTypeByName<ServerPolicy>(pool.policy);
+ }
+ }
+
+ dnsdist::configuration::updateImmutableConfiguration([&globalConfig](dnsdist::configuration::ImmutableConfiguration& config) {
+ convertImmutableFlatSettingsFromRust(globalConfig, config);
+ });
+
+ dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ convertRuntimeFlatSettingsFromRust(globalConfig, config);
+ });
+
+ dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
+ for (const auto& rule : globalConfig.query_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::RuleChain::Rules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.cache_miss_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::RuleChain::CacheMissRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.response_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::ResponseRuleChain::ResponseRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.cache_hit_response_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::ResponseRuleChain::CacheHitResponseRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.cache_inserted_response_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.self_answered_response_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::ResponseRuleChain::SelfAnsweredResponseRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+
+ for (const auto& rule : globalConfig.xfr_response_rules) {
+ boost::uuids::uuid ruleUniqueID = rule.uuid.empty() ? getUniqueID() : getUniqueID(std::string(rule.uuid));
+ dnsdist::rules::add(config.d_ruleChains, dnsdist::rules::ResponseRuleChain::XFRResponseRules, std::move(rule.selector.selector->d_rule), rule.action.action->d_action, std::string(rule.name), ruleUniqueID, 0);
+ }
+ });
+
+ s_registeredTypesMap.lock()->clear();
+ return true;
+ }
+ catch (const ::rust::Error& exp) {
+ errlog("Rust error while opening YAML file %s: %s", fileName, exp.what());
+ }
+ catch (const std::exception& exp) {
+ errlog("C++ error while opening YAML file %s: %s", fileName, exp.what());
+ }
+ s_registeredTypesMap.lock()->clear();
+ return false;
+#else
+ (void)fileName;
+ throw std::runtime_error("Unsupported YAML configuration");
+#endif /* HAVE_YAML_CONFIGURATION */
+}
+}
+
+#if defined(HAVE_YAML_CONFIGURATION)
+namespace dnsdist::rust::settings
+{
+
+static std::shared_ptr<DNSSelector> newDNSSelector(std::shared_ptr<DNSRule>&& rule, const ::rust::String& name)
+{
+ auto selector = std::make_shared<DNSSelector>();
+ selector->d_name = std::string(name);
+ selector->d_rule = std::move(rule);
+ dnsdist::configuration::yaml::registerType(selector, name);
+ return selector;
+}
+
+static std::shared_ptr<DNSActionWrapper> newDNSActionWrapper(std::shared_ptr<DNSAction>&& action, const ::rust::String& name)
+{
+ auto wrapper = std::make_shared<DNSActionWrapper>();
+ wrapper->d_name = std::string(name);
+ wrapper->d_action = std::move(action);
+ dnsdist::configuration::yaml::registerType(wrapper, name);
+ return wrapper;
+}
+
+static std::shared_ptr<DNSResponseActionWrapper> newDNSResponseActionWrapper(std::shared_ptr<DNSResponseAction>&& action, const ::rust::String& name)
+{
+ auto wrapper = std::make_shared<DNSResponseActionWrapper>();
+ wrapper->d_name = std::string(name);
+ wrapper->d_action = std::move(action);
+ dnsdist::configuration::yaml::registerType(wrapper, name);
+ return wrapper;
+}
+
+static dnsdist::ResponseConfig convertResponseConfig(const dnsdist::rust::settings::ResponseConfig& rustConfig)
+{
+ dnsdist::ResponseConfig cppConfig{};
+ cppConfig.setAA = rustConfig.set_aa;
+ cppConfig.setAD = rustConfig.set_ad;
+ cppConfig.setRA = rustConfig.set_ra;
+ cppConfig.ttl = rustConfig.ttl;
+ return cppConfig;
+}
+
+static dnsdist::actions::SOAParams convertSOAParams(const dnsdist::rust::settings::SOAParams& soa)
+{
+ dnsdist::actions::SOAParams cppSOA{};
+ cppSOA.serial = soa.serial;
+ cppSOA.refresh = soa.refresh;
+ cppSOA.retry = soa.retry;
+ cppSOA.expire = soa.expire;
+ cppSOA.minimum = soa.minimum;
+ return cppSOA;
+}
+
+static std::vector<::SVCRecordParameters> convertSVCRecordParameters(const ::rust::Vec<dnsdist::rust::settings::SVCRecordParameters>& rustParameters)
+{
+ std::vector<::SVCRecordParameters> cppParameters;
+ for (const auto& rustConfig : rustParameters) {
+ ::SVCRecordParameters cppConfig{};
+ for (auto param : rustConfig.mandatory_params) {
+ cppConfig.mandatoryParams.insert(param);
+ }
+ for (const auto& alpn : rustConfig.alpns) {
+ cppConfig.alpns.emplace_back(alpn);
+ }
+ for (const auto& hint : rustConfig.ipv4_hints) {
+ cppConfig.ipv4hints.emplace_back(std::string(hint));
+ }
+ for (const auto& hint : rustConfig.ipv6_hints) {
+ cppConfig.ipv6hints.emplace_back(std::string(hint));
+ }
+ for (const auto& param : rustConfig.additional_params) {
+ cppConfig.additionalParams.emplace_back(param.key, std::string(param.value));
+ }
+ cppConfig.target = DNSName(std::string(rustConfig.target));
+ if (rustConfig.port != 0) {
+ cppConfig.port = rustConfig.port;
+ }
+ cppConfig.priority = rustConfig.priority;
+ cppConfig.noDefaultAlpn = rustConfig.no_default_alpn;
+
+ cppParameters.emplace_back(std::move(cppConfig));
+ }
+ return cppParameters;
+}
+
+template <class T>
+T convertLuaFunction(const ::rust::String& context, const ::rust::String& name)
+{
+ T function;
+ if (!dnsdist::configuration::yaml::getOptionalLuaFunction<T>(function, name)) {
+ throw std::runtime_error("Context '" + std::string(context) + "' is referring to a non-existent Lua function '" + std::string(name) + "'");
+ }
+ return function;
+}
+
+std::shared_ptr<DNSActionWrapper> getContinueAction(const ContinueActionConfiguration& config)
+{
+ auto action = dnsdist::actions::getContinueAction(config.action.action->d_action);
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getSetProxyProtocolValuesAction(const SetProxyProtocolValuesActionConfiguration& config)
+{
+ std::vector<std::pair<uint8_t, std::string>> values;
+ for (const auto& value : config.values) {
+ values.emplace_back(value.key, std::string(value.value));
+ }
+ auto action = dnsdist::actions::getSetProxyProtocolValuesAction(values);
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getSpoofPacketAction(const SpoofPacketActionConfiguration& config)
+{
+ if (config.response.size() < sizeof(dnsheader)) {
+ throw std::runtime_error(std::string("SpoofPacketAction: given packet len is too small"));
+ }
+ auto action = dnsdist::actions::getSpoofAction(PacketBuffer(config.response.data(), config.response.data() + config.response.size()));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getSpoofAction(const SpoofActionConfiguration& config)
+{
+ std::vector<ComboAddress> addresses;
+ for (const auto& addr : config.ips) {
+ addresses.emplace_back(std::string(addr));
+ }
+ auto action = dnsdist::actions::getSpoofAction(addresses, convertResponseConfig(config.vars));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getSpoofCNAMEAction(const SpoofCNAMEActionConfiguration& config)
+{
+ auto cname = DNSName(std::string(config.cname));
+ auto action = dnsdist::actions::getSpoofAction(cname, convertResponseConfig(config.vars));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getSpoofRawAction(const SpoofRawActionConfiguration& config)
+{
+ std::vector<std::string> raws;
+ for (const auto& answer : config.answers) {
+ raws.emplace_back(answer);
+ }
+ std::optional<uint16_t> qtypeForAny;
+ if (!config.qtype_for_any.empty()) {
+ QType qtype;
+ qtype = std::string(config.qtype_for_any);
+ qtypeForAny = qtype.getCode();
+ }
+ auto action = dnsdist::actions::getSpoofAction(raws, qtypeForAny, convertResponseConfig(config.vars));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getClearRecordTypesResponseAction(const ClearRecordTypesResponseActionConfiguration& config)
+{
+ std::unordered_set<QType> qtypes{};
+ for (const auto& type : config.types) {
+ qtypes.insert(type);
+ }
+ auto action = dnsdist::actions::getClearRecordTypesResponseAction(std::move(qtypes));
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getLimitTTLResponseAction(const LimitTTLResponseActionConfiguration& config)
+{
+ std::unordered_set<QType> capTypes;
+ for (const auto& type : config.types) {
+ capTypes.insert(QType(type));
+ }
+
+ auto action = dnsdist::actions::getLimitTTLResponseAction(config.min, config.max, capTypes);
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getSetMinTTLResponseAction(const SetMinTTLResponseActionConfiguration& config)
+{
+ auto action = dnsdist::actions::getLimitTTLResponseAction(config.min);
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getSetMaxTTLResponseAction(const SetMaxTTLResponseActionConfiguration& config)
+{
+ auto action = dnsdist::actions::getLimitTTLResponseAction(0, config.max);
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSSelector> getQNameSuffixSelector(const QNameSuffixSelectorConfiguration& config)
+{
+ SuffixMatchNode suffixes;
+ for (const auto& suffix : config.suffixes) {
+ suffixes.add(std::string(suffix));
+ }
+ return newDNSSelector(dnsdist::selectors::getQNameSuffixSelector(suffixes, config.quiet), config.name);
+}
+
+std::shared_ptr<DNSSelector> getQNameSetSelector(const QNameSetSelectorConfiguration& config)
+{
+ DNSNameSet qnames;
+ for (const auto& name : config.qnames) {
+ qnames.emplace(std::string(name));
+ }
+ return newDNSSelector(dnsdist::selectors::getQNameSetSelector(qnames), config.name);
+}
+
+std::shared_ptr<DNSSelector> getQNameSelector(const QNameSelectorConfiguration& config)
+{
+ return newDNSSelector(dnsdist::selectors::getQNameSelector(DNSName(std::string(config.qname))), config.name);
+}
+
+std::shared_ptr<DNSSelector> getNetmaskGroupSelector(const NetmaskGroupSelectorConfiguration& config)
+{
+ std::shared_ptr<NetmaskGroup> nmg;
+ if (!config.netmask_group_name.empty()) {
+ nmg = dnsdist::configuration::yaml::getRegisteredTypeByName<NetmaskGroup>(std::string(config.netmask_group_name));
+ }
+ if (!nmg) {
+ nmg = std::make_shared<NetmaskGroup>();
+ }
+ for (const auto& netmask : config.netmasks) {
+ nmg->addMask(std::string(netmask));
+ }
+ auto selector = dnsdist::selectors::getNetmaskGroupSelector(*nmg, config.source, config.quiet);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getKeyValueStoreLookupAction(const KeyValueStoreLookupActionConfiguration& config)
+{
+ auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
+ if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
+ }
+ auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
+ if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
+ }
+ auto action = dnsdist::actions::getKeyValueStoreLookupAction(kvs, lookupKey, std::string(config.destination_tag));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getKeyValueStoreRangeLookupAction(const KeyValueStoreRangeLookupActionConfiguration& config)
+{
+ auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
+ if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
+ }
+ auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
+ if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
+ }
+ auto action = dnsdist::actions::getKeyValueStoreRangeLookupAction(kvs, lookupKey, std::string(config.destination_tag));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSSelector> getKeyValueStoreLookupSelector(const KeyValueStoreLookupSelectorConfiguration& config)
+{
+ auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
+ if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
+ }
+ auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
+ if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
+ }
+ auto selector = dnsdist::selectors::getKeyValueStoreLookupSelector(kvs, lookupKey);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSSelector> getKeyValueStoreRangeLookupSelector(const KeyValueStoreRangeLookupSelectorConfiguration& config)
+{
+ auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueStore>(std::string(config.kvs_name));
+ if (!kvs && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value store named '" + std::string(config.kvs_name) + "'");
+ }
+ auto lookupKey = dnsdist::configuration::yaml::getRegisteredTypeByName<KeyValueLookupKey>(std::string(config.lookup_key_name));
+ if (!lookupKey && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the key-value lookup key named '" + std::string(config.lookup_key_name) + "'");
+ }
+ auto selector = dnsdist::selectors::getKeyValueStoreRangeLookupSelector(kvs, lookupKey);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getDnstapLogAction(const DnstapLogActionConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF) || !defined(HAVE_FSTRM)
+ throw std::runtime_error("Unable to create dnstap log action: dnstap support is not enabled");
+#else
+ auto logger = dnsdist::configuration::yaml::getRegisteredTypeByName<RemoteLoggerInterface>(std::string(config.logger_name));
+ if (!logger && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the dnstap logger named '" + std::string(config.logger_name) + "'");
+ }
+ dnsdist::actions::DnstapAlterFunction alterFunc;
+ dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::DnstapAlterFunction>(alterFunc, config.alter_function);
+ auto action = dnsdist::actions::getDnstapLogAction(std::string(config.identity), logger, alterFunc);
+ return newDNSActionWrapper(std::move(action), config.name);
+#endif
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getDnstapLogResponseAction(const DnstapLogResponseActionConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF) || !defined(HAVE_FSTRM)
+ throw std::runtime_error("Unable to create dnstap log action: dnstap support is not enabled");
+#else
+ auto logger = dnsdist::configuration::yaml::getRegisteredTypeByName<RemoteLoggerInterface>(std::string(config.logger_name));
+ if (!logger && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the dnstap logger named '" + std::string(config.logger_name) + "'");
+ }
+ dnsdist::actions::DnstapAlterResponseFunction alterFunc;
+ dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::DnstapAlterResponseFunction>(alterFunc, config.alter_function);
+ auto action = dnsdist::actions::getDnstapLogResponseAction(std::string(config.identity), logger, alterFunc);
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+#endif
+}
+
+std::shared_ptr<DNSActionWrapper> getRemoteLogAction(const RemoteLogActionConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF)
+ throw std::runtime_error("Unable to create remote log action: protobuf support is disabled");
+#else
+ auto logger = dnsdist::configuration::yaml::getRegisteredTypeByName<RemoteLoggerInterface>(std::string(config.logger_name));
+ if (!logger && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the protobuf logger named '" + std::string(config.logger_name) + "'");
+ }
+ dnsdist::actions::RemoteLogActionConfiguration actionConfig{};
+ actionConfig.logger = std::move(logger);
+ actionConfig.serverID = std::string(config.server_id);
+ actionConfig.ipEncryptKey = std::string(config.ip_encrypt_key);
+ for (const auto& meta : config.metas) {
+ actionConfig.metas.emplace_back(std::string(meta.key), ProtoBufMetaKey(std::string(meta.value)));
+ }
+ if (!config.export_tags.empty()) {
+ actionConfig.tagsToExport = std::unordered_set<std::string>();
+ for (const auto& tag : config.export_tags) {
+ actionConfig.tagsToExport->emplace(std::string(tag));
+ }
+ }
+ dnsdist::actions::ProtobufAlterFunction alterFunc;
+ if (dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::ProtobufAlterFunction>(alterFunc, config.alter_function)) {
+ actionConfig.alterQueryFunc = std::move(alterFunc);
+ }
+ auto action = dnsdist::actions::getRemoteLogAction(actionConfig);
+ return newDNSActionWrapper(std::move(action), config.name);
+#endif
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getRemoteLogResponseAction(const RemoteLogResponseActionConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF)
+ throw std::runtime_error("Unable to create remote log action: protobuf support is disabled");
+#else
+ auto logger = dnsdist::configuration::yaml::getRegisteredTypeByName<RemoteLoggerInterface>(std::string(config.logger_name));
+ if (!logger && !(dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode)) {
+ throw std::runtime_error("Unable to find the protobuf logger named '" + std::string(config.logger_name) + "'");
+ }
+ dnsdist::actions::RemoteLogActionConfiguration actionConfig{};
+ actionConfig.logger = std::move(logger);
+ actionConfig.serverID = std::string(config.server_id);
+ actionConfig.ipEncryptKey = std::string(config.ip_encrypt_key);
+ actionConfig.includeCNAME = config.include_cname;
+ for (const auto& meta : config.metas) {
+ actionConfig.metas.emplace_back(std::string(meta.key), ProtoBufMetaKey(std::string(meta.value)));
+ }
+ if (!config.export_tags.empty()) {
+ actionConfig.tagsToExport = std::unordered_set<std::string>();
+ for (const auto& tag : config.export_tags) {
+ actionConfig.tagsToExport->emplace(std::string(tag));
+ }
+ }
+ if (!config.export_extended_errors_to_meta.empty()) {
+ actionConfig.exportExtendedErrorsToMeta = std::string(config.export_extended_errors_to_meta);
+ }
+ dnsdist::actions::ProtobufAlterResponseFunction alterFunc;
+ if (dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::ProtobufAlterResponseFunction>(alterFunc, config.alter_function)) {
+ actionConfig.alterResponseFunc = std::move(alterFunc);
+ }
+ auto action = dnsdist::actions::getRemoteLogResponseAction(actionConfig);
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+#endif
+}
+
+void registerProtobufLogger(const ProtobufLoggerConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF)
+ throw std::runtime_error("Unable to create protobuf logger: protobuf support is disabled");
+#else
+ if (dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode) {
+ auto object = std::shared_ptr<RemoteLoggerInterface>(nullptr);
+ dnsdist::configuration::yaml::registerType<RemoteLoggerInterface>(object, config.name);
+ return;
+ }
+ auto object = std::shared_ptr<RemoteLoggerInterface>(std::make_shared<RemoteLogger>(ComboAddress(std::string(config.address)), config.timeout, config.max_queued_entries * 100, config.reconnect_wait_time, false));
+ dnsdist::configuration::yaml::registerType<RemoteLoggerInterface>(object, config.name);
+#endif
+}
+
+void registerDnstapLogger(const DnstapLoggerConfiguration& config)
+{
+#if defined(DISABLE_PROTOBUF) || !defined(HAVE_FSTRM)
+ throw std::runtime_error("Unable to create dnstap logger: dnstap support is disabled");
+#else
+ auto transport = boost::to_lower_copy(std::string(config.transport));
+ int family{0};
+ if (transport == "unix") {
+ family = AF_UNIX;
+ }
+ else if (transport == "tcp") {
+ family = AF_INET;
+ }
+ else {
+ throw std::runtime_error("Unsupport dnstap transport type '" + transport + "'");
+ }
+
+ if (dnsdist::configuration::yaml::s_inClientMode || dnsdist::configuration::yaml::s_inConfigCheckMode) {
+ auto object = std::shared_ptr<RemoteLoggerInterface>(nullptr);
+ dnsdist::configuration::yaml::registerType<RemoteLoggerInterface>(object, config.name);
+ return;
+ }
+
+ std::unordered_map<string, unsigned int> options;
+ options["bufferHint"] = config.buffer_hint;
+ options["flushTimeout"] = config.flush_timeout;
+ options["inputQueueSize"] = config.input_queue_size;
+ options["outputQueueSize"] = config.output_queue_size;
+ options["queueNotifyThreshold"] = config.queue_notify_threshold;
+ options["reopenInterval"] = config.reopen_interval;
+
+ auto object = std::shared_ptr<RemoteLoggerInterface>(std::make_shared<FrameStreamLogger>(family, std::string(config.address), false, options));
+ dnsdist::configuration::yaml::registerType<RemoteLoggerInterface>(object, config.name);
+#endif
+}
+
+void registerKVSObjects(const KeyValueStoresConfiguration& config)
+{
+ bool createObjects = !dnsdist::configuration::yaml::s_inClientMode && !dnsdist::configuration::yaml::s_inConfigCheckMode;
+#if defined(HAVE_LMDB)
+ for (const auto& lmdb : config.lmdb) {
+ auto store = createObjects ? std::shared_ptr<KeyValueStore>(std::make_shared<LMDBKVStore>(std::string(lmdb.file_name), std::string(lmdb.database_name), lmdb.no_lock)) : std::shared_ptr<KeyValueStore>();
+ dnsdist::configuration::yaml::registerType<KeyValueStore>(store, lmdb.name);
+ }
+#endif /* defined(HAVE_LMDB) */
+#if defined(HAVE_CDB)
+ for (const auto& cdb : config.cdb) {
+ auto store = createObjects ? std::shared_ptr<KeyValueStore>(std::make_shared<CDBKVStore>(std::string(cdb.file_name), cdb.refresh_delay)) : std::shared_ptr<KeyValueStore>();
+ dnsdist::configuration::yaml::registerType<KeyValueStore>(store, cdb.name);
+ }
+#endif /* defined(HAVE_CDB) */
+#if defined(HAVE_LMDB) || defined(HAVE_CDB)
+ for (const auto& key : config.lookup_keys.source_ip_keys) {
+ auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySourceIP>(key.v4_mask, key.v6_mask, key.include_port)) : std::shared_ptr<KeyValueLookupKey>();
+ dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
+ }
+ for (const auto& key : config.lookup_keys.qname_keys) {
+ auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyQName>(key.wire_format)) : std::shared_ptr<KeyValueLookupKey>();
+ dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
+ }
+ for (const auto& key : config.lookup_keys.suffix_keys) {
+ auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeySuffix>(key.minimum_labels, key.wire_format)) : std::shared_ptr<KeyValueLookupKey>();
+ dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
+ }
+ for (const auto& key : config.lookup_keys.tag_keys) {
+ auto lookup = createObjects ? std::shared_ptr<KeyValueLookupKey>(std::make_shared<KeyValueLookupKeyTag>(std::string(key.tag))) : std::shared_ptr<KeyValueLookupKey>();
+ dnsdist::configuration::yaml::registerType<KeyValueLookupKey>(lookup, key.name);
+ }
+#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
+}
+
+std::shared_ptr<DNSSelector> getAndSelector(const AndSelectorConfiguration& config)
+{
+ std::vector<std::shared_ptr<DNSRule>> selectors;
+ selectors.reserve(config.selectors.size());
+ for (const auto& subSelector : config.selectors) {
+ selectors.emplace_back(subSelector.selector->d_rule);
+ }
+ auto selector = dnsdist::selectors::getAndSelector(selectors);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSSelector> getOrSelector(const OrSelectorConfiguration& config)
+{
+ std::vector<std::shared_ptr<DNSRule>> selectors;
+ selectors.reserve(config.selectors.size());
+ for (const auto& subSelector : config.selectors) {
+ selectors.emplace_back(subSelector.selector->d_rule);
+ }
+ auto selector = dnsdist::selectors::getOrSelector(selectors);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSSelector> getNotSelector(const NotSelectorConfiguration& config)
+{
+ auto selector = dnsdist::selectors::getNotSelector(config.selector.selector->d_rule);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSSelector> getByNameSelector(const ByNameSelectorConfiguration& config)
+{
+ return dnsdist::configuration::yaml::getRegisteredTypeByName<DNSSelector>(config.selector_name);
+}
+
+#include "dnsdist-rust-bridge-actions-generated.cc"
+#include "dnsdist-rust-bridge-selectors-generated.cc"
+}
+#endif /* defined(HAVE_YAML_CONFIGURATION) */
+// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!!
+// START INCLUDE ./rust-pre-in.rs
use serde::{Deserialize, Serialize};
mod helpers;
}
#[cxx::bridge(namespace = dnsdist::rust::settings)]
-mod dnsdistsetttings {
+mod dnsdistsettings {
+ #[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ResponseConfig {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ set_aa: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ set_ad: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ set_ra: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ttl: u32,
+ }
+
+ #[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SOAParams {
+ serial: u32,
+ refresh: u32,
+ retry: u32,
+ expire: u32,
+ minimum: u32,
+ }
+
+ #[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SVCRecordAdditionalParams {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ key: u16,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ value: String,
+ }
+
+ #[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SVCRecordParameters {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ mandatory_params: Vec<u16>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ alpns: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ipv4_hints: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ipv6_hints: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ additional_params: Vec<SVCRecordAdditionalParams>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ target: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ port: u16,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ priority: u16,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ no_default_alpn: bool,
+ }
+
+ struct SharedDNSSelector {
+ selector: SharedPtr<DNSSelector>,
+ }
+ struct SharedDNSAction {
+ action: SharedPtr<DNSActionWrapper>,
+ }
+
+ struct SharedDNSResponseAction {
+ action: SharedPtr<DNSResponseActionWrapper>,
+ }
+// END INCLUDE ./rust-pre-in.rs
#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
- struct CarbonConfiguration {
+ struct AllowActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
- address: String,
+ name: String,
+ }
+
+ #[derive(Default)]
+ struct ContinueActionConfiguration {
+ name: String,
+ action: SharedDNSAction,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DelayActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ msec: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DnstapLogActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ identity: String,
+ #[serde(rename = "logger-name", )]
+ logger_name: String,
+ #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
+ alter_function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DropActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetEDNSOptionActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: u32,
+ data: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ERCodeActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ rcode: u8,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HTTPStatusActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ status: u16,
+ body: String,
+ #[serde(rename = "content-type", default, skip_serializing_if = "crate::is_default")]
+ content_type: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KeyValueStoreLookupActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "kvs-name", )]
+ kvs_name: String,
+ #[serde(rename = "lookup-key-name", )]
+ lookup_key_name: String,
+ #[serde(rename = "destination-tag", )]
+ destination_tag: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KeyValueStoreRangeLookupActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "kvs-name", )]
+ kvs_name: String,
+ #[serde(rename = "lookup-key-name", )]
+ lookup_key_name: String,
+ #[serde(rename = "destination-tag", )]
+ destination_tag: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LogActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "file-name", default, skip_serializing_if = "crate::is_default")]
+ file_name: String,
+ #[serde(default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ binary: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ append: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ buffered: bool,
+ #[serde(rename = "verbose-only", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ verbose_only: bool,
+ #[serde(rename = "include-timestamp", default, skip_serializing_if = "crate::is_default")]
+ include_timestamp: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFIActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFIPerThreadActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct NegativeAndSOAActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ nxd: bool,
+ zone: String,
+ ttl: u32,
+ mname: String,
+ rname: String,
+ #[serde(rename = "soa-parameters", )]
+ soa_parameters: SOAParams,
+ #[serde(rename = "soa-in-authority", default, skip_serializing_if = "crate::is_default")]
+ soa_in_authority: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct NoneActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PoolActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "pool-name", )]
+ pool_name: String,
+ #[serde(rename = "stop-processing", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ stop_processing: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QPSActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ limit: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QPSPoolActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ limit: u32,
+ #[serde(rename = "pool-name", )]
+ pool_name: String,
+ #[serde(rename = "stop-processing", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ stop_processing: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RCodeActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ rcode: u8,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RemoteLogActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "logger-name", )]
+ logger_name: String,
+ #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
+ alter_function: String,
+ #[serde(rename = "server-id", default, skip_serializing_if = "crate::is_default")]
+ server_id: String,
+ #[serde(rename = "ip-encrypt-key", default, skip_serializing_if = "crate::is_default")]
+ ip_encrypt_key: String,
+ #[serde(rename = "export-tags", default, skip_serializing_if = "crate::is_default")]
+ export_tags: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ metas: Vec<ProtoBufMetaConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetAdditionalProxyProtocolValueActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "proxy-type", )]
+ proxy_type: u8,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetDisableECSActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetDisableValidationActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetECSActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ ipv4: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ipv6: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetECSOverrideActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "override-existing", )]
+ override_existing: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetECSPrefixLengthActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ ipv4: u16,
+ ipv6: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetExtendedDNSErrorActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "info-code", )]
+ info_code: u16,
+ #[serde(rename = "extra-text", default, skip_serializing_if = "crate::is_default")]
+ extra_text: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetMacAddrActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetMaxReturnedTTLActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ max: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetNoRecurseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetProxyProtocolValuesActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ values: Vec<ProxyProtocolValueConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetSkipCacheActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetTagActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ tag: String,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetTempFailureCacheTTLActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "maxTTL", )]
+ maxttl: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SNMPTrapActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
- interval: u16
+ reason: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SpoofActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ ips: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SpoofCNAMEActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ cname: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SpoofPacketActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ response: String,
+ len: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SpoofRawActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ answers: Vec<String>,
+ #[serde(rename = "qtype-for-any", default, skip_serializing_if = "crate::is_default")]
+ qtype_for_any: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SpoofSVCActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ parameters: Vec<SVCRecordParameters>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ vars: ResponseConfig,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TCActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TeeActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ rca: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ lca: String,
+ #[serde(rename = "add-ecs", default, skip_serializing_if = "crate::is_default")]
+ add_ecs: bool,
+ #[serde(rename = "add-proxy-protocol", default, skip_serializing_if = "crate::is_default")]
+ add_proxy_protocol: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct AllowResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ClearRecordTypesResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ types: Vec<u16>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DelayResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ msec: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DnstapLogResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ identity: String,
+ #[serde(rename = "logger-name", )]
+ logger_name: String,
+ #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
+ alter_function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DropResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LimitTTLResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ min: u32,
+ max: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ types: Vec<u16>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LogResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "file-name", default, skip_serializing_if = "crate::is_default")]
+ file_name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ append: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ buffered: bool,
+ #[serde(rename = "verbose-only", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ verbose_only: bool,
+ #[serde(rename = "include-timestamp", default, skip_serializing_if = "crate::is_default")]
+ include_timestamp: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFIResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFIPerThreadResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RemoteLogResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "logger-name", )]
+ logger_name: String,
+ #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
+ alter_function: String,
+ #[serde(rename = "server-id", default, skip_serializing_if = "crate::is_default")]
+ server_id: String,
+ #[serde(rename = "ip-encrypt-key", default, skip_serializing_if = "crate::is_default")]
+ ip_encrypt_key: String,
+ #[serde(rename = "include-cname", default, skip_serializing_if = "crate::is_default")]
+ include_cname: bool,
+ #[serde(rename = "export-tags", default, skip_serializing_if = "crate::is_default")]
+ export_tags: Vec<String>,
+ #[serde(rename = "export-extended-errors-to-meta", default, skip_serializing_if = "crate::is_default")]
+ export_extended_errors_to_meta: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ metas: Vec<ProtoBufMetaConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetExtendedDNSErrorResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "info-code", )]
+ info_code: u16,
+ #[serde(rename = "extra-text", default, skip_serializing_if = "crate::is_default")]
+ extra_text: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetMaxReturnedTTLResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ max: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetMaxTTLResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ max: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetMinTTLResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ min: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetReducedTTLResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ percentage: u8,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetSkipCacheResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SetTagResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ tag: String,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SNMPTrapResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ reason: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TCResponseActionConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct AllSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Default)]
+ struct AndSelectorConfiguration {
+ name: String,
+ selectors: Vec<SharedDNSSelector>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ByNameSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "selector-name", )]
+ selector_name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DNSSECSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DSTPortSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ port: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct EDNSOptionSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "option-code", )]
+ option_code: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct EDNSVersionSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ version: u8,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ERCodeSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ rcode: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HTTPHeaderSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ header: String,
+ expression: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HTTPPathSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ path: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HTTPPathRegexSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ expression: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KeyValueStoreLookupSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "kvs-name", )]
+ kvs_name: String,
+ #[serde(rename = "lookup-key-name", )]
+ lookup_key_name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KeyValueStoreRangeLookupSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "kvs-name", )]
+ kvs_name: String,
+ #[serde(rename = "lookup-key-name", )]
+ lookup_key_name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFISelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ function: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LuaFFIPerThreadSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct MaxQPSSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ qps: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ burst: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct MaxQPSIPSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ qps: u32,
+ #[serde(rename = "ipv4-mask", default = "crate::U8::<32>::value", skip_serializing_if = "crate::U8::<32>::is_equal")]
+ ipv4_mask: u8,
+ #[serde(rename = "ipv6-mask", default = "crate::U8::<64>::value", skip_serializing_if = "crate::U8::<64>::is_equal")]
+ ipv6_mask: u8,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ burst: u32,
+ #[serde(default = "crate::U32::<300>::value", skip_serializing_if = "crate::U32::<300>::is_equal")]
+ expiration: u32,
+ #[serde(rename = "cleanup-delay", default = "crate::U32::<60>::value", skip_serializing_if = "crate::U32::<60>::is_equal")]
+ cleanup_delay: u32,
+ #[serde(rename = "scan-fraction", default = "crate::U32::<10>::value", skip_serializing_if = "crate::U32::<10>::is_equal")]
+ scan_fraction: u32,
+ #[serde(default = "crate::U32::<10>::value", skip_serializing_if = "crate::U32::<10>::is_equal")]
+ shards: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct NetmaskGroupSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "netmask-group-name", default, skip_serializing_if = "crate::is_default")]
+ netmask_group_name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ netmasks: Vec<String>,
+ #[serde(default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ source: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ quiet: bool,
+ }
+
+ #[derive(Default)]
+ struct NotSelectorConfiguration {
+ name: String,
+ selector: SharedDNSSelector,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct OpcodeSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ code: u8,
+ }
+
+ #[derive(Default)]
+ struct OrSelectorConfiguration {
+ name: String,
+ selectors: Vec<SharedDNSSelector>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PayloadSizeSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ comparison: String,
+ size: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PoolAvailableSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ pool: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PoolOutstandingSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ pool: String,
+ #[serde(rename = "max-outstanding", )]
+ max_outstanding: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProbaSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ probability: f64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProxyProtocolValueSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "option-type", )]
+ option_type: u8,
+ #[serde(rename = "option-value", default, skip_serializing_if = "crate::is_default")]
+ option_value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QClassSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ qclass: String,
+ #[serde(rename = "numeric-value", default, skip_serializing_if = "crate::is_default")]
+ numeric_value: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QNameSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ qname: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QNameLabelsCountSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "min-labels-count", )]
+ min_labels_count: u16,
+ #[serde(rename = "max-labels-count", )]
+ max_labels_count: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QNameSetSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ qnames: Vec<String>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QNameSuffixSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ suffixes: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ quiet: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QNameWireLengthSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ min: u16,
+ max: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QTypeSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ qtype: String,
+ #[serde(rename = "numeric-value", default, skip_serializing_if = "crate::is_default")]
+ numeric_value: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RCodeSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ rcode: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RDSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RE2SelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ expression: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RecordsCountSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ section: u8,
+ minimum: u16,
+ maximum: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RecordsTypeCountSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ section: u8,
+ #[serde(rename = "record-type", )]
+ record_type: u16,
+ minimum: u16,
+ maximum: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RegexSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ expression: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SNISelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(rename = "server-name", )]
+ server_name: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TagSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ tag: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TCPSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ tcp: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TrailingDataSelectorConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ }
+
+ #[derive(Default)]
+ struct GlobalConfiguration {
+ acl: Vec<String>,
+ backends: Vec<BackendConfiguration>,
+ binds: Vec<BindConfiguration>,
+ cache_hit_response_rules: Vec<ResponseRuleConfiguration>,
+ cache_inserted_response_rules: Vec<ResponseRuleConfiguration>,
+ cache_miss_rules: Vec<QueryRuleConfiguration>,
+ cache_settings: CacheSettingsConfiguration,
+ console: ConsoleConfiguration,
+ dynamic_rules: Vec<DynamicRulesConfiguration>,
+ dynamic_rules_settings: DynamicRulesSettingsConfiguration,
+ edns_client_subnet: EdnsClientSubnetConfiguration,
+ general: GeneralConfiguration,
+ key_value_stores: KeyValueStoresConfiguration,
+ load_balancing_policies: LoadBalancingPoliciesConfiguration,
+ metrics: MetricsConfiguration,
+ packet_caches: Vec<PacketCacheConfiguration>,
+ pools: Vec<PoolConfiguration>,
+ proxy_protocol: ProxyProtocolConfiguration,
+ query_count: QueryCountConfiguration,
+ query_rules: Vec<QueryRuleConfiguration>,
+ remote_logging: RemoteLoggingConfiguration,
+ response_rules: Vec<ResponseRuleConfiguration>,
+ ring_buffers: RingBuffersConfiguration,
+ security_polling: SecurityPollingConfiguration,
+ selectors: Vec<SharedDNSSelector>,
+ self_answered_response_rules: Vec<ResponseRuleConfiguration>,
+ snmp: SnmpConfiguration,
+ tuning: TuningConfiguration,
+ webserver: WebserverConfiguration,
+ xfr_response_rules: Vec<ResponseRuleConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct MetricsConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ carbon: Vec<CarbonConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct CarbonConfiguration {
+ address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default = "crate::U32::<30>::value", skip_serializing_if = "crate::U32::<30>::is_equal")]
+ interval: u32,
+ #[serde(rename = "namespace", default, skip_serializing_if = "crate::is_default")]
+ name_space: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ instance: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RemoteLoggingConfiguration {
+ #[serde(rename = "protobuf-loggers", default, skip_serializing_if = "crate::is_default")]
+ protobuf_loggers: Vec<ProtobufLoggerConfiguration>,
+ #[serde(rename = "dnstap-loggers", default, skip_serializing_if = "crate::is_default")]
+ dnstap_loggers: Vec<DnstapLoggerConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProtobufLoggerConfiguration {
+ name: String,
+ address: String,
+ #[serde(default = "crate::U16::<2>::value", skip_serializing_if = "crate::U16::<2>::is_equal")]
+ timeout: u16,
+ #[serde(rename = "max-queued-entries", default = "crate::U64::<100>::value", skip_serializing_if = "crate::U64::<100>::is_equal")]
+ max_queued_entries: u64,
+ #[serde(rename = "reconnect-wait-time", default = "crate::U8::<1>::value", skip_serializing_if = "crate::U8::<1>::is_equal")]
+ reconnect_wait_time: u8,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DnstapLoggerConfiguration {
+ name: String,
+ transport: String,
+ address: String,
+ #[serde(rename = "buffer-hint", default, skip_serializing_if = "crate::is_default")]
+ buffer_hint: u64,
+ #[serde(rename = "flush-timeout", default, skip_serializing_if = "crate::is_default")]
+ flush_timeout: u64,
+ #[serde(rename = "input-queue-size", default, skip_serializing_if = "crate::is_default")]
+ input_queue_size: u64,
+ #[serde(rename = "output-queue-size", default, skip_serializing_if = "crate::is_default")]
+ output_queue_size: u64,
+ #[serde(rename = "queue-notify-threshold", default, skip_serializing_if = "crate::is_default")]
+ queue_notify_threshold: u64,
+ #[serde(rename = "reopen-interval", default, skip_serializing_if = "crate::is_default")]
+ reopen_interval: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProtoBufMetaConfiguration {
+ key: String,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LMDBKVStoreConfiguration {
+ name: String,
+ #[serde(rename = "file-name", )]
+ file_name: String,
+ #[serde(rename = "database-name", )]
+ database_name: String,
+ #[serde(rename = "no-lock", default, skip_serializing_if = "crate::is_default")]
+ no_lock: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct CDBKVStoreConfiguration {
+ name: String,
+ #[serde(rename = "file-name", )]
+ file_name: String,
+ #[serde(rename = "refresh-delay", )]
+ refresh_delay: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KVSLookupKeySourceIPConfiguration {
+ name: String,
+ #[serde(rename = "v4-mask", default = "crate::U8::<32>::value", skip_serializing_if = "crate::U8::<32>::is_equal")]
+ v4_mask: u8,
+ #[serde(rename = "v6-mask", default = "crate::U8::<128>::value", skip_serializing_if = "crate::U8::<128>::is_equal")]
+ v6_mask: u8,
+ #[serde(rename = "include-port", default, skip_serializing_if = "crate::is_default")]
+ include_port: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KVSLookupKeyQNameConfiguration {
+ name: String,
+ #[serde(rename = "wire-format", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ wire_format: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KVSLookupKeySuffixConfiguration {
+ name: String,
+ #[serde(rename = "minimum-labels", default, skip_serializing_if = "crate::is_default")]
+ minimum_labels: u16,
+ #[serde(rename = "wire-format", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ wire_format: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KVSLookupKeyTagConfiguration {
+ name: String,
+ tag: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KVSLookupKeysConfiguration {
+ #[serde(rename = "source-ip-keys", default, skip_serializing_if = "crate::is_default")]
+ source_ip_keys: Vec<KVSLookupKeySourceIPConfiguration>,
+ #[serde(rename = "qname-keys", default, skip_serializing_if = "crate::is_default")]
+ qname_keys: Vec<KVSLookupKeyQNameConfiguration>,
+ #[serde(rename = "suffix-keys", default, skip_serializing_if = "crate::is_default")]
+ suffix_keys: Vec<KVSLookupKeySuffixConfiguration>,
+ #[serde(rename = "tag-keys", default, skip_serializing_if = "crate::is_default")]
+ tag_keys: Vec<KVSLookupKeyTagConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct KeyValueStoresConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ lmdb: Vec<LMDBKVStoreConfiguration>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ cdb: Vec<CDBKVStoreConfiguration>,
+ #[serde(rename = "lookup-keys", default, skip_serializing_if = "crate::is_default")]
+ lookup_keys: KVSLookupKeysConfiguration,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct WebserverConfiguration {
+ #[serde(rename = "listen-address", default, skip_serializing_if = "crate::is_default")]
+ listen_address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ password: String,
+ #[serde(rename = "api-key", default, skip_serializing_if = "crate::is_default")]
+ api_key: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ acl: Vec<String>,
+ #[serde(rename = "api-requires-authentication", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ api_requires_authentication: bool,
+ #[serde(rename = "stats-require-authentication", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ stats_require_authentication: bool,
+ #[serde(rename = "dashboard-requires-authentication", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ dashboard_requires_authentication: bool,
+ #[serde(rename = "max-concurrent-connections", default = "crate::U32::<100>::value", skip_serializing_if = "crate::U32::<100>::is_equal")]
+ max_concurrent_connections: u32,
+ #[serde(rename = "hash-plaintext-credentials", default, skip_serializing_if = "crate::is_default")]
+ hash_plaintext_credentials: bool,
+ #[serde(rename = "custom-headers", default, skip_serializing_if = "crate::is_default")]
+ custom_headers: Vec<HttpCustomResponseHeaderConfiguration>,
+ #[serde(rename = "api-configuration-directory", default, skip_serializing_if = "crate::is_default")]
+ api_configuration_directory: String,
+ #[serde(rename = "api-read-write", default, skip_serializing_if = "crate::is_default")]
+ api_read_write: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ConsoleConfiguration {
+ #[serde(rename = "listen-address", default, skip_serializing_if = "crate::is_default")]
+ listen_address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ key: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ acl: Vec<String>,
+ #[serde(rename = "maximum-output-size", default = "crate::U32::<10000000>::value", skip_serializing_if = "crate::U32::<10000000>::is_equal")]
+ maximum_output_size: u32,
+ #[serde(rename = "log-connections", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ log_connections: bool,
+ #[serde(rename = "max-concurrent-connections", default, skip_serializing_if = "crate::is_default")]
+ max_concurrent_connections: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct EdnsClientSubnetConfiguration {
+ #[serde(rename = "override-existing", default, skip_serializing_if = "crate::is_default")]
+ override_existing: bool,
+ #[serde(rename = "source-prefix-v4", default = "crate::U8::<32>::value", skip_serializing_if = "crate::U8::<32>::is_equal")]
+ source_prefix_v4: u8,
+ #[serde(rename = "source-prefix-v6", default = "crate::U8::<56>::value", skip_serializing_if = "crate::U8::<56>::is_equal")]
+ source_prefix_v6: u8,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DynamicRulesSettingsConfiguration {
+ #[serde(rename = "purge-interval", default = "crate::U64::<60>::value", skip_serializing_if = "crate::U64::<60>::is_equal")]
+ purge_interval: u64,
+ #[serde(rename = "default-action", default = "crate::default_value_dynamic_rules_settings_default_action", skip_serializing_if = "crate::default_value_equal_dynamic_rules_settings_default_action")]
+ default_action: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DynamicRuleConfiguration {
+ #[serde(rename = "type", )]
+ rule_type: String,
+ seconds: u32,
+ #[serde(rename = "action-duration", )]
+ action_duration: u32,
+ comment: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ rate: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ratio: f64,
+ #[serde(default = "crate::default_value_dynamic_rule_action", skip_serializing_if = "crate::default_value_equal_dynamic_rule_action")]
+ action: String,
+ #[serde(rename = "warning-rate", default, skip_serializing_if = "crate::is_default")]
+ warning_rate: u32,
+ #[serde(rename = "warning-ratio", default, skip_serializing_if = "crate::is_default")]
+ warning_ratio: f64,
+ #[serde(rename = "tag-name", default, skip_serializing_if = "crate::is_default")]
+ tag_name: String,
+ #[serde(rename = "tag-value", default = "crate::default_value_dynamic_rule_tag_value", skip_serializing_if = "crate::default_value_equal_dynamic_rule_tag_value")]
+ tag_value: String,
+ #[serde(rename = "visitor-function", default, skip_serializing_if = "crate::is_default")]
+ visitor_function: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ rcode: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ qtype: String,
+ #[serde(rename = "minimum-number-of-responses", default, skip_serializing_if = "crate::is_default")]
+ minimum_number_of_responses: u32,
+ #[serde(rename = "minimum-global-cache-hit-ratio", default, skip_serializing_if = "crate::is_default")]
+ minimum_global_cache_hit_ratio: f64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DynamicRulesConfiguration {
+ name: String,
+ #[serde(rename = "mask-ipv4", default = "crate::U8::<32>::value", skip_serializing_if = "crate::U8::<32>::is_equal")]
+ mask_ipv4: u8,
+ #[serde(rename = "mask-ipv6", default = "crate::U8::<64>::value", skip_serializing_if = "crate::U8::<64>::is_equal")]
+ mask_ipv6: u8,
+ #[serde(rename = "mask-port", default, skip_serializing_if = "crate::is_default")]
+ mask_port: u8,
+ #[serde(rename = "exclude-ranges", default, skip_serializing_if = "crate::is_default")]
+ exclude_ranges: Vec<String>,
+ #[serde(rename = "include-ranges", default, skip_serializing_if = "crate::is_default")]
+ include_ranges: Vec<String>,
+ #[serde(rename = "exclude-domains", default, skip_serializing_if = "crate::is_default")]
+ exclude_domains: Vec<String>,
+ rules: Vec<DynamicRuleConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct RingBuffersConfiguration {
+ #[serde(default = "crate::U64::<10000>::value", skip_serializing_if = "crate::U64::<10000>::is_equal")]
+ size: u64,
+ #[serde(default = "crate::U64::<10>::value", skip_serializing_if = "crate::U64::<10>::is_equal")]
+ shards: u64,
+ #[serde(rename = "lock-retries", default = "crate::U64::<5>::value", skip_serializing_if = "crate::U64::<5>::is_equal")]
+ lock_retries: u64,
+ #[serde(rename = "record-queries", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ record_queries: bool,
+ #[serde(rename = "record-responses", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ record_responses: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingTlsCertificateKeyPairConfiguration {
+ certificate: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ key: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ password: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingTlsConfiguration {
+ #[serde(default = "crate::default_value_incoming_tls_provider", skip_serializing_if = "crate::default_value_equal_incoming_tls_provider")]
+ provider: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ certificates: Vec<IncomingTlsCertificateKeyPairConfiguration>,
+ #[serde(rename = "ignore-errors", default, skip_serializing_if = "crate::is_default")]
+ ignore_errors: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ciphers: String,
+ #[serde(rename = "ciphers-tls-13", default, skip_serializing_if = "crate::is_default")]
+ ciphers_tls_13: String,
+ #[serde(rename = "minimum-version", default = "crate::default_value_incoming_tls_minimum_version", skip_serializing_if = "crate::default_value_equal_incoming_tls_minimum_version")]
+ minimum_version: String,
+ #[serde(rename = "ticket-key-file", default, skip_serializing_if = "crate::is_default")]
+ ticket_key_file: String,
+ #[serde(rename = "tickets-keys-rotation-delay", default = "crate::U32::<43200>::value", skip_serializing_if = "crate::U32::<43200>::is_equal")]
+ tickets_keys_rotation_delay: u32,
+ #[serde(rename = "number-of-tickets-keys", default = "crate::U32::<5>::value", skip_serializing_if = "crate::U32::<5>::is_equal")]
+ number_of_tickets_keys: u32,
+ #[serde(rename = "prefer-server-ciphers", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ prefer_server_ciphers: bool,
+ #[serde(rename = "session-timeout", default, skip_serializing_if = "crate::is_default")]
+ session_timeout: u32,
+ #[serde(rename = "session-tickets", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ session_tickets: bool,
+ #[serde(rename = "number-of-stored-sessions", default = "crate::U32::<20480>::value", skip_serializing_if = "crate::U32::<20480>::is_equal")]
+ number_of_stored_sessions: u32,
+ #[serde(rename = "ocsp-response-files", default, skip_serializing_if = "crate::is_default")]
+ ocsp_response_files: Vec<String>,
+ #[serde(rename = "key-log-file", default, skip_serializing_if = "crate::is_default")]
+ key_log_file: String,
+ #[serde(rename = "release-buffers", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ release_buffers: bool,
+ #[serde(rename = "enable-renegotiation", default, skip_serializing_if = "crate::is_default")]
+ enable_renegotiation: bool,
+ #[serde(rename = "async-mode", default, skip_serializing_if = "crate::is_default")]
+ async_mode: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ktls: bool,
+ #[serde(rename = "read-ahead", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ read_ahead: bool,
+ #[serde(rename = "proxy-protocol-outside-tls", default, skip_serializing_if = "crate::is_default")]
+ proxy_protocol_outside_tls: bool,
+ #[serde(rename = "ignore-configuration-errors", default, skip_serializing_if = "crate::is_default")]
+ ignore_configuration_errors: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct OutgoingTlsConfiguration {
+ #[serde(default = "crate::default_value_outgoing_tls_provider", skip_serializing_if = "crate::default_value_equal_outgoing_tls_provider")]
+ provider: String,
+ #[serde(rename = "subject-name", default, skip_serializing_if = "crate::is_default")]
+ subject_name: String,
+ #[serde(rename = "subject-address", default, skip_serializing_if = "crate::is_default")]
+ subject_address: String,
+ #[serde(rename = "validate-certificate", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ validate_certificate: bool,
+ #[serde(rename = "ca-store", default, skip_serializing_if = "crate::is_default")]
+ ca_store: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ciphers: String,
+ #[serde(rename = "ciphers-tls-13", default, skip_serializing_if = "crate::is_default")]
+ ciphers_tls_13: String,
+ #[serde(rename = "key-log-file", default, skip_serializing_if = "crate::is_default")]
+ key_log_file: String,
+ #[serde(rename = "release-buffers", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ release_buffers: bool,
+ #[serde(rename = "enable-renegotiation", default, skip_serializing_if = "crate::is_default")]
+ enable_renegotiation: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ktls: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HttpCustomResponseHeaderConfiguration {
+ key: String,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HttpResponsesMapConfiguration {
+ expression: String,
+ status: u16,
+ content: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ headers: Vec<HttpCustomResponseHeaderConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingDohConfiguration {
+ #[serde(default = "crate::default_value_incoming_doh_provider", skip_serializing_if = "crate::default_value_equal_incoming_doh_provider")]
+ provider: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ paths: Vec<String>,
+ #[serde(rename = "idle-timeout", default = "crate::U64::<30>::value", skip_serializing_if = "crate::U64::<30>::is_equal")]
+ idle_timeout: u64,
+ #[serde(rename = "server-tokens", default = "crate::default_value_incoming_doh_server_tokens", skip_serializing_if = "crate::default_value_equal_incoming_doh_server_tokens")]
+ server_tokens: String,
+ #[serde(rename = "send-cache-control-headers", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ send_cache_control_headers: bool,
+ #[serde(rename = "keep-incoming-headers", default, skip_serializing_if = "crate::is_default")]
+ keep_incoming_headers: bool,
+ #[serde(rename = "trust-forwarded-for-header", default, skip_serializing_if = "crate::is_default")]
+ trust_forwarded_for_header: bool,
+ #[serde(rename = "early-acl-drop", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ early_acl_drop: bool,
+ #[serde(rename = "exact-path-matching", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ exact_path_matching: bool,
+ #[serde(rename = "internal-pipe-buffer-size", default = "crate::U32::<1048576>::value", skip_serializing_if = "crate::U32::<1048576>::is_equal")]
+ internal_pipe_buffer_size: u32,
+ #[serde(rename = "custom-response-headers", default, skip_serializing_if = "crate::is_default")]
+ custom_response_headers: Vec<HttpCustomResponseHeaderConfiguration>,
+ #[serde(rename = "responses-map", default, skip_serializing_if = "crate::is_default")]
+ responses_map: Vec<HttpResponsesMapConfiguration>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingDoqConfiguration {
+ #[serde(default = "crate::U64::<65535>::value", skip_serializing_if = "crate::U64::<65535>::is_equal")]
+ max_concurrent_queries_per_connection: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingQuicConfiguration {
+ #[serde(rename = "idle-timeout", default = "crate::U64::<5>::value", skip_serializing_if = "crate::U64::<5>::is_equal")]
+ idle_timeout: u64,
+ #[serde(rename = "congestion-control-algorithm", default = "crate::default_value_incoming_quic_congestion_control_algorithm", skip_serializing_if = "crate::default_value_equal_incoming_quic_congestion_control_algorithm")]
+ congestion_control_algorithm: String,
+ #[serde(rename = "internal-pipe-buffer-size", default = "crate::U32::<1048576>::value", skip_serializing_if = "crate::U32::<1048576>::is_equal")]
+ internal_pipe_buffer_size: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct OutgoingDohConfiguration {
+ #[serde(default = "crate::default_value_outgoing_doh_path", skip_serializing_if = "crate::default_value_equal_outgoing_doh_path")]
+ path: String,
+ #[serde(rename = "add-x-forwarded-headers", default, skip_serializing_if = "crate::is_default")]
+ add_x_forwarded_headers: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct IncomingTcpConfiguration {
+ #[serde(rename = "max-in-flight-queries", default, skip_serializing_if = "crate::is_default")]
+ max_in_flight_queries: u32,
+ #[serde(rename = "listen-queue-size", default, skip_serializing_if = "crate::is_default")]
+ listen_queue_size: u32,
+ #[serde(rename = "fast-open-queue-size", default, skip_serializing_if = "crate::is_default")]
+ fast_open_queue_size: u32,
+ #[serde(rename = "max-concurrent-connections", default, skip_serializing_if = "crate::is_default")]
+ max_concurrent_connections: u32,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct BindConfiguration {
+ #[serde(rename = "listen-address", )]
+ listen_address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ reuseport: bool,
+ #[serde(default = "crate::default_value_bind_protocol", skip_serializing_if = "crate::default_value_equal_bind_protocol")]
+ protocol: String,
+ #[serde(default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ threads: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ interface: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ cpus: String,
+ #[serde(rename = "enable-proxy-protocol", default, skip_serializing_if = "crate::is_default")]
+ enable_proxy_protocol: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tcp: IncomingTcpConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tls: IncomingTlsConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ doh: IncomingDohConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ doq: IncomingDoqConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ quic: IncomingQuicConfiguration,
+ #[serde(rename = "additional-addresses", default, skip_serializing_if = "crate::is_default")]
+ additional_addresses: Vec<String>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct OutgoingTcpConfiguration {
+ #[serde(rename = "connect-timeout", default = "crate::U16::<5>::value", skip_serializing_if = "crate::U16::<5>::is_equal")]
+ connect_timeout: u16,
+ #[serde(rename = "send-timeout", default = "crate::U16::<30>::value", skip_serializing_if = "crate::U16::<30>::is_equal")]
+ send_timeout: u16,
+ #[serde(rename = "receive-timeout", default = "crate::U16::<30>::value", skip_serializing_if = "crate::U16::<30>::is_equal")]
+ receive_timeout: u16,
+ #[serde(rename = "fast-open", default, skip_serializing_if = "crate::is_default")]
+ fast_open: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProxyProtocolValueConfiguration {
+ key: u8,
+ value: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LazyHealthCheckConfiguration {
+ #[serde(default = "crate::U16::<30>::value", skip_serializing_if = "crate::U16::<30>::is_equal")]
+ interval: u16,
+ #[serde(rename = "min-sample-count", default = "crate::U16::<1>::value", skip_serializing_if = "crate::U16::<1>::is_equal")]
+ min_sample_count: u16,
+ #[serde(default = "crate::default_value_lazy_health_check_mode", skip_serializing_if = "crate::default_value_equal_lazy_health_check_mode")]
+ mode: String,
+ #[serde(rename = "sample-size", default = "crate::U16::<100>::value", skip_serializing_if = "crate::U16::<100>::is_equal")]
+ sample_size: u16,
+ #[serde(default = "crate::U16::<20>::value", skip_serializing_if = "crate::U16::<20>::is_equal")]
+ threshold: u16,
+ #[serde(rename = "use-exponential-back-off", default, skip_serializing_if = "crate::is_default")]
+ use_exponential_back_off: bool,
+ #[serde(rename = "max-back-off", default = "crate::U16::<3600>::value", skip_serializing_if = "crate::U16::<3600>::is_equal")]
+ max_back_off: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct HealthCheckConfiguration {
+ #[serde(default = "crate::default_value_health_check_mode", skip_serializing_if = "crate::default_value_equal_health_check_mode")]
+ mode: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ qname: String,
+ #[serde(default = "crate::default_value_health_check_qclass", skip_serializing_if = "crate::default_value_equal_health_check_qclass")]
+ qclass: String,
+ #[serde(default = "crate::default_value_health_check_qtype", skip_serializing_if = "crate::default_value_equal_health_check_qtype")]
+ qtype: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ function: String,
+ #[serde(default = "crate::U16::<1000>::value", skip_serializing_if = "crate::U16::<1000>::is_equal")]
+ timeout: u16,
+ #[serde(rename = "set-cd", default, skip_serializing_if = "crate::is_default")]
+ set_cd: bool,
+ #[serde(rename = "max-failures", default = "crate::U8::<1>::value", skip_serializing_if = "crate::U8::<1>::is_equal")]
+ max_failures: u8,
+ #[serde(default = "crate::U8::<1>::value", skip_serializing_if = "crate::U8::<1>::is_equal")]
+ rise: u8,
+ #[serde(default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ interval: u32,
+ #[serde(rename = "must-resolve", default, skip_serializing_if = "crate::is_default")]
+ must_resolve: bool,
+ #[serde(rename = "use-tcp", default, skip_serializing_if = "crate::is_default")]
+ use_tcp: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ lazy: LazyHealthCheckConfiguration,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct OutgoingAutoUpgradeConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ enabled: bool,
+ #[serde(default = "crate::U32::<3600>::value", skip_serializing_if = "crate::U32::<3600>::is_equal")]
+ interval: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ keep: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ pool: String,
+ #[serde(rename = "doh-key", default = "crate::U8::<7>::value", skip_serializing_if = "crate::U8::<7>::is_equal")]
+ doh_key: u8,
+ #[serde(rename = "use-lazy-health-check", default, skip_serializing_if = "crate::is_default")]
+ use_lazy_health_check: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct BackendConfiguration {
+ address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ id: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ protocol: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tls: OutgoingTlsConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ doh: OutgoingDohConfiguration,
+ #[serde(rename = "use-client-subnet", default, skip_serializing_if = "crate::is_default")]
+ use_client_subnet: bool,
+ #[serde(rename = "use-proxy-protocol", default, skip_serializing_if = "crate::is_default")]
+ use_proxy_protocol: bool,
+ #[serde(rename = "queries-per-second", default, skip_serializing_if = "crate::is_default")]
+ queries_per_second: u32,
+ #[serde(default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ order: u32,
+ #[serde(default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ weight: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ pools: Vec<String>,
+ #[serde(default = "crate::U16::<5>::value", skip_serializing_if = "crate::U16::<5>::is_equal")]
+ retries: u16,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tcp: OutgoingTcpConfiguration,
+ #[serde(rename = "ip-bind-addr-no-port", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ ip_bind_addr_no_port: bool,
+ #[serde(rename = "health-checks", default, skip_serializing_if = "crate::is_default")]
+ health_checks: HealthCheckConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ source: String,
+ #[serde(default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ sockets: u32,
+ #[serde(rename = "disable-zero-scope", default, skip_serializing_if = "crate::is_default")]
+ disable_zero_scope: bool,
+ #[serde(rename = "reconnect-on-up", default, skip_serializing_if = "crate::is_default")]
+ reconnect_on_up: bool,
+ #[serde(rename = "max-in-flight", default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ max_in_flight: u32,
+ #[serde(rename = "tcp-only", default, skip_serializing_if = "crate::is_default")]
+ tcp_only: bool,
+ #[serde(rename = "auto-upgrade", default, skip_serializing_if = "crate::is_default")]
+ auto_upgrade: OutgoingAutoUpgradeConfiguration,
+ #[serde(rename = "max-concurrent-tcp-connections", default, skip_serializing_if = "crate::is_default")]
+ max_concurrent_tcp_connections: u32,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ktls: bool,
+ #[serde(rename = "proxy-protocol-advertise-tls", default, skip_serializing_if = "crate::is_default")]
+ proxy_protocol_advertise_tls: bool,
+ #[serde(rename = "xsk-sockets", default, skip_serializing_if = "crate::is_default")]
+ xsk_sockets: Vec<String>,
+ #[serde(rename = "mac-address", default, skip_serializing_if = "crate::is_default")]
+ mac_address: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ cpus: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TuningConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ doh: DohTuningConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tcp: TcpTuningConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tls: TlsTuningConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ udp: UdpTuningConfiguration,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TcpTuningConfiguration {
+ #[serde(rename = "worker-threads", default = "crate::U32::<10>::value", skip_serializing_if = "crate::U32::<10>::is_equal")]
+ worker_threads: u32,
+ #[serde(rename = "receive-timeout", default = "crate::U32::<2>::value", skip_serializing_if = "crate::U32::<2>::is_equal")]
+ receive_timeout: u32,
+ #[serde(rename = "send-timeout", default = "crate::U32::<2>::value", skip_serializing_if = "crate::U32::<2>::is_equal")]
+ send_timeout: u32,
+ #[serde(rename = "max-queries-per-connection", default, skip_serializing_if = "crate::is_default")]
+ max_queries_per_connection: u64,
+ #[serde(rename = "max-connection-duration", default, skip_serializing_if = "crate::is_default")]
+ max_connection_duration: u64,
+ #[serde(rename = "max-queued-connections", default = "crate::U64::<10000>::value", skip_serializing_if = "crate::U64::<10000>::is_equal")]
+ max_queued_connections: u64,
+ #[serde(rename = "internal-pipe-buffer-size", default = "crate::U32::<1048576>::value", skip_serializing_if = "crate::U32::<1048576>::is_equal")]
+ internal_pipe_buffer_size: u32,
+ #[serde(rename = "outgoing-max-idle-time", default = "crate::U64::<300>::value", skip_serializing_if = "crate::U64::<300>::is_equal")]
+ outgoing_max_idle_time: u64,
+ #[serde(rename = "outgoing-cleanup-interval", default = "crate::U64::<60>::value", skip_serializing_if = "crate::U64::<60>::is_equal")]
+ outgoing_cleanup_interval: u64,
+ #[serde(rename = "outgoing-max-idle-connection-per-backend", default = "crate::U64::<10>::value", skip_serializing_if = "crate::U64::<10>::is_equal")]
+ outgoing_max_idle_connection_per_backend: u64,
+ #[serde(rename = "max-connections-per-client", default, skip_serializing_if = "crate::is_default")]
+ max_connections_per_client: u32,
+ #[serde(rename = "fast-open-key", default, skip_serializing_if = "crate::is_default")]
+ fast_open_key: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct UdpTuningConfiguration {
+ #[serde(rename = "messages-per-round", default = "crate::U32::<1>::value", skip_serializing_if = "crate::U32::<1>::is_equal")]
+ messages_per_round: u32,
+ #[serde(rename = "send-buffer-size", default, skip_serializing_if = "crate::is_default")]
+ send_buffer_size: u32,
+ #[serde(rename = "receive-buffer-size", default, skip_serializing_if = "crate::is_default")]
+ receive_buffer_size: u32,
+ #[serde(rename = "max-outstanding-per-backend", default = "crate::U32::<65535>::value", skip_serializing_if = "crate::U32::<65535>::is_equal")]
+ max_outstanding_per_backend: u32,
+ #[serde(default = "crate::U8::<2>::value", skip_serializing_if = "crate::U8::<2>::is_equal")]
+ timeout: u8,
+ #[serde(rename = "randomize-outgoing-sockets-to-backend", default, skip_serializing_if = "crate::is_default")]
+ randomize_outgoing_sockets_to_backend: bool,
+ #[serde(rename = "randomize-ids-to-backend", default, skip_serializing_if = "crate::is_default")]
+ randomize_ids_to_backend: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct TlsTuningConfiguration {
+ #[serde(rename = "outgoing-tickets-cache-cleanup-delay", default = "crate::U16::<60>::value", skip_serializing_if = "crate::U16::<60>::is_equal")]
+ outgoing_tickets_cache_cleanup_delay: u16,
+ #[serde(rename = "outgoing-tickets-cache-validity", default = "crate::U16::<600>::value", skip_serializing_if = "crate::U16::<600>::is_equal")]
+ outgoing_tickets_cache_validity: u16,
+ #[serde(rename = "max-outgoing-tickets-per-backend", default = "crate::U16::<20>::value", skip_serializing_if = "crate::U16::<20>::is_equal")]
+ max_outgoing_tickets_per_backend: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct DohTuningConfiguration {
+ #[serde(rename = "outgoing-worker-threads", default = "crate::U32::<10>::value", skip_serializing_if = "crate::U32::<10>::is_equal")]
+ outgoing_worker_threads: u32,
+ #[serde(rename = "outgoing-max-idle-time", default = "crate::U64::<300>::value", skip_serializing_if = "crate::U64::<300>::is_equal")]
+ outgoing_max_idle_time: u64,
+ #[serde(rename = "outgoing-cleanup-interval", default = "crate::U64::<60>::value", skip_serializing_if = "crate::U64::<60>::is_equal")]
+ outgoing_cleanup_interval: u64,
+ #[serde(rename = "outgoing-max-idle-connection-per-backend", default = "crate::U64::<10>::value", skip_serializing_if = "crate::U64::<10>::is_equal")]
+ outgoing_max_idle_connection_per_backend: u64,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct CacheSettingsConfiguration {
+ #[serde(rename = "stale-entries-ttl", default, skip_serializing_if = "crate::is_default")]
+ stale_entries_ttl: u32,
+ #[serde(rename = "cleaning-delay", default = "crate::U16::<60>::value", skip_serializing_if = "crate::U16::<60>::is_equal")]
+ cleaning_delay: u16,
+ #[serde(rename = "cleaning-percentage", default = "crate::U16::<100>::value", skip_serializing_if = "crate::U16::<100>::is_equal")]
+ cleaning_percentage: u16,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SecurityPollingConfiguration {
+ #[serde(rename = "polling-interval", default = "crate::U32::<3600>::value", skip_serializing_if = "crate::U32::<3600>::is_equal")]
+ polling_interval: u32,
+ #[serde(default = "crate::default_value_security_polling_suffix", skip_serializing_if = "crate::default_value_equal_security_polling_suffix")]
+ suffix: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct GeneralConfiguration {
+ #[serde(rename = "edns-udp-payload-size-self-generated-answers", default = "crate::U16::<1232>::value", skip_serializing_if = "crate::U16::<1232>::is_equal")]
+ edns_udp_payload_size_self_generated_answers: u16,
+ #[serde(rename = "add-edns-to-self-generated-answers", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ add_edns_to_self_generated_answers: bool,
+ #[serde(rename = "truncate-tc-answers", default, skip_serializing_if = "crate::is_default")]
+ truncate_tc_answers: bool,
+ #[serde(rename = "fixup-case", default, skip_serializing_if = "crate::is_default")]
+ fixup_case: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ verbose: bool,
+ #[serde(rename = "verbose-health-checks", default, skip_serializing_if = "crate::is_default")]
+ verbose_health_checks: bool,
+ #[serde(rename = "allow-empty-responses", default, skip_serializing_if = "crate::is_default")]
+ allow_empty_responses: bool,
+ #[serde(rename = "drop-empty-queries", default, skip_serializing_if = "crate::is_default")]
+ drop_empty_queries: bool,
+ #[serde(rename = "capabilities-to-retain", default, skip_serializing_if = "crate::is_default")]
+ capabilities_to_retain: Vec<String>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PacketCacheConfiguration {
+ name: String,
+ size: u64,
+ #[serde(rename = "deferrable-insert-lock", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ deferrable_insert_lock: bool,
+ #[serde(rename = "dont-age", default, skip_serializing_if = "crate::is_default")]
+ dont_age: bool,
+ #[serde(rename = "keep-stale-data", default, skip_serializing_if = "crate::is_default")]
+ keep_stale_data: bool,
+ #[serde(rename = "max-negative-ttl", default = "crate::U32::<3600>::value", skip_serializing_if = "crate::U32::<3600>::is_equal")]
+ max_negative_ttl: u32,
+ #[serde(rename = "max-ttl", default = "crate::U32::<86400>::value", skip_serializing_if = "crate::U32::<86400>::is_equal")]
+ max_ttl: u32,
+ #[serde(rename = "min-ttl", default, skip_serializing_if = "crate::is_default")]
+ min_ttl: u32,
+ #[serde(default = "crate::U32::<20>::value", skip_serializing_if = "crate::U32::<20>::is_equal")]
+ shards: u32,
+ #[serde(rename = "parse-ecs", default, skip_serializing_if = "crate::is_default")]
+ parse_ecs: bool,
+ #[serde(rename = "stale-ttl", default = "crate::U32::<60>::value", skip_serializing_if = "crate::U32::<60>::is_equal")]
+ stale_ttl: u32,
+ #[serde(rename = "temporary-failure-ttl", default = "crate::U32::<60>::value", skip_serializing_if = "crate::U32::<60>::is_equal")]
+ temporary_failure_ttl: u32,
+ #[serde(rename = "cookie-hashing", default, skip_serializing_if = "crate::is_default")]
+ cookie_hashing: bool,
+ #[serde(rename = "maximum-entry-size", default, skip_serializing_if = "crate::is_default")]
+ maximum_entry_size: u32,
+ #[serde(rename = "options-to-skip", default, skip_serializing_if = "crate::is_default")]
+ options_to_skip: Vec<String>,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct ProxyProtocolConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ acl: Vec<String>,
+ #[serde(rename = "maximum-payload-size", default = "crate::U32::<512>::value", skip_serializing_if = "crate::U32::<512>::is_equal")]
+ maximum_payload_size: u32,
+ #[serde(rename = "apply-acl-to-proxied-clients", default, skip_serializing_if = "crate::is_default")]
+ apply_acl_to_proxied_clients: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct SnmpConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ enabled: bool,
+ #[serde(rename = "traps-enabled", default, skip_serializing_if = "crate::is_default")]
+ traps_enabled: bool,
+ #[serde(rename = "daemon-socket", default, skip_serializing_if = "crate::is_default")]
+ daemon_socket: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct QueryCountConfiguration {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ enabled: bool,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ filter: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct PoolConfiguration {
+ name: String,
+ #[serde(rename = "packet-cache", default, skip_serializing_if = "crate::is_default")]
+ packet_cache: String,
+ #[serde(default = "crate::default_value_pool_policy", skip_serializing_if = "crate::default_value_equal_pool_policy")]
+ policy: String,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct CustomLoadBalancingPolicyConfiguration {
+ name: String,
+ function: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ ffi: bool,
+ #[serde(rename = "per-thread", default, skip_serializing_if = "crate::is_default")]
+ per_thread: bool,
+ }
+
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct LoadBalancingPoliciesConfiguration {
+ #[serde(rename = "servfail-on-no-server", default, skip_serializing_if = "crate::is_default")]
+ servfail_on_no_server: bool,
+ #[serde(rename = "round-robin-servfail-on-no-server", default, skip_serializing_if = "crate::is_default")]
+ round_robin_servfail_on_no_server: bool,
+ #[serde(rename = "weighted-balancing-factor", default, skip_serializing_if = "crate::is_default")]
+ weighted_balancing_factor: f64,
+ #[serde(rename = "consistent-hashing-balancing-factor", default, skip_serializing_if = "crate::is_default")]
+ consistent_hashing_balancing_factor: f64,
+ #[serde(rename = "custom-policies", default, skip_serializing_if = "crate::is_default")]
+ custom_policies: Vec<CustomLoadBalancingPolicyConfiguration>,
+ #[serde(rename = "hash-perturbation", default, skip_serializing_if = "crate::is_default")]
+ hash_perturbation: u32,
+ }
+
+ struct QueryRuleConfiguration {
+ name: String,
+ uuid: String,
+ selector: SharedDNSSelector,
+ action: SharedDNSAction,
+ }
+
+ struct ResponseRuleConfiguration {
+ name: String,
+ uuid: String,
+ selector: SharedDNSSelector,
+ action: SharedDNSResponseAction,
+ }
+
+
+ /*
+ * Functions callable from Rust (actions and selectors)
+ */
+ unsafe extern "C++" {
+ fn getAllowAction(config: &AllowActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getContinueAction(config: &ContinueActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getDelayAction(config: &DelayActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getDnstapLogAction(config: &DnstapLogActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getDropAction(config: &DropActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetEDNSOptionAction(config: &SetEDNSOptionActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getERCodeAction(config: &ERCodeActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getHTTPStatusAction(config: &HTTPStatusActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getKeyValueStoreLookupAction(config: &KeyValueStoreLookupActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getKeyValueStoreRangeLookupAction(config: &KeyValueStoreRangeLookupActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getLogAction(config: &LogActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getLuaAction(config: &LuaActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getLuaFFIAction(config: &LuaFFIActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getLuaFFIPerThreadAction(config: &LuaFFIPerThreadActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getNegativeAndSOAAction(config: &NegativeAndSOAActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getNoneAction(config: &NoneActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getPoolAction(config: &PoolActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getQPSAction(config: &QPSActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getQPSPoolAction(config: &QPSPoolActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getRCodeAction(config: &RCodeActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getRemoteLogAction(config: &RemoteLogActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetAdditionalProxyProtocolValueAction(config: &SetAdditionalProxyProtocolValueActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetDisableECSAction(config: &SetDisableECSActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetDisableValidationAction(config: &SetDisableValidationActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetECSAction(config: &SetECSActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetECSOverrideAction(config: &SetECSOverrideActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetECSPrefixLengthAction(config: &SetECSPrefixLengthActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetExtendedDNSErrorAction(config: &SetExtendedDNSErrorActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetMacAddrAction(config: &SetMacAddrActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetMaxReturnedTTLAction(config: &SetMaxReturnedTTLActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetNoRecurseAction(config: &SetNoRecurseActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetProxyProtocolValuesAction(config: &SetProxyProtocolValuesActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetSkipCacheAction(config: &SetSkipCacheActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetTagAction(config: &SetTagActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSetTempFailureCacheTTLAction(config: &SetTempFailureCacheTTLActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSNMPTrapAction(config: &SNMPTrapActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSpoofAction(config: &SpoofActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSpoofCNAMEAction(config: &SpoofCNAMEActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSpoofPacketAction(config: &SpoofPacketActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSpoofRawAction(config: &SpoofRawActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getSpoofSVCAction(config: &SpoofSVCActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getTCAction(config: &TCActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getTeeAction(config: &TeeActionConfiguration) -> SharedPtr<DNSActionWrapper>;
+ fn getAllowResponseAction(config: &AllowResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getClearRecordTypesResponseAction(config: &ClearRecordTypesResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getDelayResponseAction(config: &DelayResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getDnstapLogResponseAction(config: &DnstapLogResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getDropResponseAction(config: &DropResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getLimitTTLResponseAction(config: &LimitTTLResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getLogResponseAction(config: &LogResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getLuaResponseAction(config: &LuaResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getLuaFFIResponseAction(config: &LuaFFIResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getLuaFFIPerThreadResponseAction(config: &LuaFFIPerThreadResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getRemoteLogResponseAction(config: &RemoteLogResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetExtendedDNSErrorResponseAction(config: &SetExtendedDNSErrorResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetMaxReturnedTTLResponseAction(config: &SetMaxReturnedTTLResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetMaxTTLResponseAction(config: &SetMaxTTLResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetMinTTLResponseAction(config: &SetMinTTLResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetReducedTTLResponseAction(config: &SetReducedTTLResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetSkipCacheResponseAction(config: &SetSkipCacheResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSetTagResponseAction(config: &SetTagResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getSNMPTrapResponseAction(config: &SNMPTrapResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getTCResponseAction(config: &TCResponseActionConfiguration) -> SharedPtr<DNSResponseActionWrapper>;
+ fn getAllSelector(config: &AllSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getAndSelector(config: &AndSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getByNameSelector(config: &ByNameSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getDNSSECSelector(config: &DNSSECSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getDSTPortSelector(config: &DSTPortSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getEDNSOptionSelector(config: &EDNSOptionSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getEDNSVersionSelector(config: &EDNSVersionSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getERCodeSelector(config: &ERCodeSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getHTTPHeaderSelector(config: &HTTPHeaderSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getHTTPPathSelector(config: &HTTPPathSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getHTTPPathRegexSelector(config: &HTTPPathRegexSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getKeyValueStoreLookupSelector(config: &KeyValueStoreLookupSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getKeyValueStoreRangeLookupSelector(config: &KeyValueStoreRangeLookupSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getLuaSelector(config: &LuaSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getLuaFFISelector(config: &LuaFFISelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getLuaFFIPerThreadSelector(config: &LuaFFIPerThreadSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getMaxQPSSelector(config: &MaxQPSSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getMaxQPSIPSelector(config: &MaxQPSIPSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getNetmaskGroupSelector(config: &NetmaskGroupSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getNotSelector(config: &NotSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getOpcodeSelector(config: &OpcodeSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getOrSelector(config: &OrSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getPayloadSizeSelector(config: &PayloadSizeSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getPoolAvailableSelector(config: &PoolAvailableSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getPoolOutstandingSelector(config: &PoolOutstandingSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getProbaSelector(config: &ProbaSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getProxyProtocolValueSelector(config: &ProxyProtocolValueSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQClassSelector(config: &QClassSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQNameSelector(config: &QNameSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQNameLabelsCountSelector(config: &QNameLabelsCountSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQNameSetSelector(config: &QNameSetSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQNameSuffixSelector(config: &QNameSuffixSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQNameWireLengthSelector(config: &QNameWireLengthSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getQTypeSelector(config: &QTypeSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRCodeSelector(config: &RCodeSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRDSelector(config: &RDSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRE2Selector(config: &RE2SelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRecordsCountSelector(config: &RecordsCountSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRecordsTypeCountSelector(config: &RecordsTypeCountSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getRegexSelector(config: &RegexSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getSNISelector(config: &SNISelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getTagSelector(config: &TagSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getTCPSelector(config: &TCPSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ fn getTrailingDataSelector(config: &TrailingDataSelectorConfiguration) -> SharedPtr<DNSSelector>;
+ }
+// START INCLUDE ./rust-middle-in.rs
+ /*
+ * Functions callable from C++
+ */
+ extern "Rust" {
+ fn from_yaml_string(str: &str) -> Result<GlobalConfiguration>;
+ }
+ /*
+ * Functions callable from Rust
+ */
+ unsafe extern "C++" {
+ include!("dnsdist-rust-bridge.hh");
+ type DNSSelector;
+ type DNSActionWrapper;
+ type DNSResponseActionWrapper;
+ fn registerProtobufLogger(config: &ProtobufLoggerConfiguration);
+ fn registerDnstapLogger(config: &DnstapLoggerConfiguration);
+ fn registerKVSObjects(config: &KeyValueStoresConfiguration);
+ }
+}
+
+impl Default for dnsdistsettings::SharedDNSAction {
+ fn default() -> dnsdistsettings::SharedDNSAction {
+ dnsdistsettings::SharedDNSAction {
+ action: cxx::SharedPtr::null(),
+ }
+ }
+}
+
+impl Default for dnsdistsettings::SharedDNSSelector {
+ fn default() -> dnsdistsettings::SharedDNSSelector {
+ dnsdistsettings::SharedDNSSelector {
+ selector: cxx::SharedPtr::null(),
+ }
+ }
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct AndSelectorConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ selectors: Vec<Selector>,
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct OrSelectorConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ selectors: Vec<Selector>,
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct NotSelectorConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ selector: Box<Selector>,
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct ContinueActionConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ action: Box<Action>,
+}
+
+impl Selector {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+impl Action {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+impl ResponseAction {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct QueryRuleConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ uuid: String,
+ selector: Selector,
+ action: Action,
+}
+
+impl QueryRuleConfigurationSerde {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+#[derive(Default, Deserialize, Serialize, Debug, PartialEq)]
+#[serde(deny_unknown_fields)]
+struct ResponseRuleConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ name: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ uuid: String,
+ selector: Selector,
+ action: ResponseAction,
+}
+
+impl ResponseRuleConfigurationSerde {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+impl dnsdistsettings::SharedDNSAction {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+
+impl dnsdistsettings::SharedDNSResponseAction {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+// END INCLUDE ./rust-middle-in.rs
+ #[derive(Deserialize, Serialize, Debug, PartialEq)]
+ #[serde(deny_unknown_fields)]
+ struct GlobalConfigurationSerde {
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ acl: Vec<String>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ backends: Vec<dnsdistsettings::BackendConfiguration>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ binds: Vec<dnsdistsettings::BindConfiguration>,
+ #[serde(rename = "cache-hit-response-rules", default, skip_serializing_if = "crate::is_default")]
+ cache_hit_response_rules: Vec<ResponseRuleConfigurationSerde>,
+ #[serde(rename = "cache-inserted-response-rules", default, skip_serializing_if = "crate::is_default")]
+ cache_inserted_response_rules: Vec<ResponseRuleConfigurationSerde>,
+ #[serde(rename = "cache-miss-rules", default, skip_serializing_if = "crate::is_default")]
+ cache_miss_rules: Vec<QueryRuleConfigurationSerde>,
+ #[serde(rename = "cache-settings", default, skip_serializing_if = "crate::is_default")]
+ cache_settings: dnsdistsettings::CacheSettingsConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ console: dnsdistsettings::ConsoleConfiguration,
+ #[serde(rename = "dynamic-rules", default, skip_serializing_if = "crate::is_default")]
+ dynamic_rules: Vec<dnsdistsettings::DynamicRulesConfiguration>,
+ #[serde(rename = "dynamic-rules-settings", default, skip_serializing_if = "crate::is_default")]
+ dynamic_rules_settings: dnsdistsettings::DynamicRulesSettingsConfiguration,
+ #[serde(rename = "edns-client-subnet", default, skip_serializing_if = "crate::is_default")]
+ edns_client_subnet: dnsdistsettings::EdnsClientSubnetConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ general: dnsdistsettings::GeneralConfiguration,
+ #[serde(rename = "key-value-stores", default, skip_serializing_if = "crate::is_default")]
+ key_value_stores: dnsdistsettings::KeyValueStoresConfiguration,
+ #[serde(rename = "load-balancing-policies", default, skip_serializing_if = "crate::is_default")]
+ load_balancing_policies: dnsdistsettings::LoadBalancingPoliciesConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ metrics: dnsdistsettings::MetricsConfiguration,
+ #[serde(rename = "packet-caches", default, skip_serializing_if = "crate::is_default")]
+ packet_caches: Vec<dnsdistsettings::PacketCacheConfiguration>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ pools: Vec<dnsdistsettings::PoolConfiguration>,
+ #[serde(rename = "proxy-protocol", default, skip_serializing_if = "crate::is_default")]
+ proxy_protocol: dnsdistsettings::ProxyProtocolConfiguration,
+ #[serde(rename = "query-count", default, skip_serializing_if = "crate::is_default")]
+ query_count: dnsdistsettings::QueryCountConfiguration,
+ #[serde(rename = "query-rules", default, skip_serializing_if = "crate::is_default")]
+ query_rules: Vec<QueryRuleConfigurationSerde>,
+ #[serde(rename = "remote-logging", default, skip_serializing_if = "crate::is_default")]
+ remote_logging: dnsdistsettings::RemoteLoggingConfiguration,
+ #[serde(rename = "response-rules", default, skip_serializing_if = "crate::is_default")]
+ response_rules: Vec<ResponseRuleConfigurationSerde>,
+ #[serde(rename = "ring-buffers", default, skip_serializing_if = "crate::is_default")]
+ ring_buffers: dnsdistsettings::RingBuffersConfiguration,
+ #[serde(rename = "security-polling", default, skip_serializing_if = "crate::is_default")]
+ security_polling: dnsdistsettings::SecurityPollingConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ selectors: Vec<Selector>,
+ #[serde(rename = "self-answered-response-rules", default, skip_serializing_if = "crate::is_default")]
+ self_answered_response_rules: Vec<ResponseRuleConfigurationSerde>,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ snmp: dnsdistsettings::SnmpConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ tuning: dnsdistsettings::TuningConfiguration,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ webserver: dnsdistsettings::WebserverConfiguration,
+ #[serde(rename = "xfr-response-rules", default, skip_serializing_if = "crate::is_default")]
+ xfr_response_rules: Vec<ResponseRuleConfigurationSerde>,
+ }
+
+#[derive(Default, Serialize, Deserialize, Debug, PartialEq)]
+#[serde(tag = "type")]
+enum Action {
+ #[default]
+ Default,
+ Allow(dnsdistsettings::AllowActionConfiguration),
+ Continue(ContinueActionConfigurationSerde),
+ Delay(dnsdistsettings::DelayActionConfiguration),
+ DnstapLog(dnsdistsettings::DnstapLogActionConfiguration),
+ Drop(dnsdistsettings::DropActionConfiguration),
+ SetEDNSOption(dnsdistsettings::SetEDNSOptionActionConfiguration),
+ ERCode(dnsdistsettings::ERCodeActionConfiguration),
+ HTTPStatus(dnsdistsettings::HTTPStatusActionConfiguration),
+ KeyValueStoreLookup(dnsdistsettings::KeyValueStoreLookupActionConfiguration),
+ KeyValueStoreRangeLookup(dnsdistsettings::KeyValueStoreRangeLookupActionConfiguration),
+ Log(dnsdistsettings::LogActionConfiguration),
+ Lua(dnsdistsettings::LuaActionConfiguration),
+ LuaFFI(dnsdistsettings::LuaFFIActionConfiguration),
+ LuaFFIPerThread(dnsdistsettings::LuaFFIPerThreadActionConfiguration),
+ NegativeAndSOA(dnsdistsettings::NegativeAndSOAActionConfiguration),
+ None(dnsdistsettings::NoneActionConfiguration),
+ Pool(dnsdistsettings::PoolActionConfiguration),
+ QPS(dnsdistsettings::QPSActionConfiguration),
+ QPSPool(dnsdistsettings::QPSPoolActionConfiguration),
+ RCode(dnsdistsettings::RCodeActionConfiguration),
+ RemoteLog(dnsdistsettings::RemoteLogActionConfiguration),
+ SetAdditionalProxyProtocolValue(dnsdistsettings::SetAdditionalProxyProtocolValueActionConfiguration),
+ SetDisableECS(dnsdistsettings::SetDisableECSActionConfiguration),
+ SetDisableValidation(dnsdistsettings::SetDisableValidationActionConfiguration),
+ SetECS(dnsdistsettings::SetECSActionConfiguration),
+ SetECSOverride(dnsdistsettings::SetECSOverrideActionConfiguration),
+ SetECSPrefixLength(dnsdistsettings::SetECSPrefixLengthActionConfiguration),
+ SetExtendedDNSError(dnsdistsettings::SetExtendedDNSErrorActionConfiguration),
+ SetMacAddr(dnsdistsettings::SetMacAddrActionConfiguration),
+ SetMaxReturnedTTL(dnsdistsettings::SetMaxReturnedTTLActionConfiguration),
+ SetNoRecurse(dnsdistsettings::SetNoRecurseActionConfiguration),
+ SetProxyProtocolValues(dnsdistsettings::SetProxyProtocolValuesActionConfiguration),
+ SetSkipCache(dnsdistsettings::SetSkipCacheActionConfiguration),
+ SetTag(dnsdistsettings::SetTagActionConfiguration),
+ SetTempFailureCacheTTL(dnsdistsettings::SetTempFailureCacheTTLActionConfiguration),
+ SNMPTrap(dnsdistsettings::SNMPTrapActionConfiguration),
+ Spoof(dnsdistsettings::SpoofActionConfiguration),
+ SpoofCNAME(dnsdistsettings::SpoofCNAMEActionConfiguration),
+ SpoofPacket(dnsdistsettings::SpoofPacketActionConfiguration),
+ SpoofRaw(dnsdistsettings::SpoofRawActionConfiguration),
+ SpoofSVC(dnsdistsettings::SpoofSVCActionConfiguration),
+ TC(dnsdistsettings::TCActionConfiguration),
+ Tee(dnsdistsettings::TeeActionConfiguration),
+}
+
+#[derive(Default, Serialize, Deserialize, Debug, PartialEq)]
+#[serde(tag = "type")]
+enum ResponseAction {
+ #[default]
+ Default,
+ Allow(dnsdistsettings::AllowResponseActionConfiguration),
+ ClearRecordTypes(dnsdistsettings::ClearRecordTypesResponseActionConfiguration),
+ Delay(dnsdistsettings::DelayResponseActionConfiguration),
+ DnstapLog(dnsdistsettings::DnstapLogResponseActionConfiguration),
+ Drop(dnsdistsettings::DropResponseActionConfiguration),
+ LimitTTL(dnsdistsettings::LimitTTLResponseActionConfiguration),
+ Log(dnsdistsettings::LogResponseActionConfiguration),
+ Lua(dnsdistsettings::LuaResponseActionConfiguration),
+ LuaFFI(dnsdistsettings::LuaFFIResponseActionConfiguration),
+ LuaFFIPerThread(dnsdistsettings::LuaFFIPerThreadResponseActionConfiguration),
+ RemoteLog(dnsdistsettings::RemoteLogResponseActionConfiguration),
+ SetExtendedDNSError(dnsdistsettings::SetExtendedDNSErrorResponseActionConfiguration),
+ SetMaxReturnedTTL(dnsdistsettings::SetMaxReturnedTTLResponseActionConfiguration),
+ SetMaxTTL(dnsdistsettings::SetMaxTTLResponseActionConfiguration),
+ SetMinTTL(dnsdistsettings::SetMinTTLResponseActionConfiguration),
+ SetReducedTTL(dnsdistsettings::SetReducedTTLResponseActionConfiguration),
+ SetSkipCache(dnsdistsettings::SetSkipCacheResponseActionConfiguration),
+ SetTag(dnsdistsettings::SetTagResponseActionConfiguration),
+ SNMPTrap(dnsdistsettings::SNMPTrapResponseActionConfiguration),
+ TC(dnsdistsettings::TCResponseActionConfiguration),
+}
+
+#[derive(Default, Serialize, Deserialize, Debug, PartialEq)]
+#[serde(tag = "type")]
+enum Selector {
+ #[default]
+ Default,
+ All(dnsdistsettings::AllSelectorConfiguration),
+ And(AndSelectorConfigurationSerde),
+ ByName(dnsdistsettings::ByNameSelectorConfiguration),
+ DNSSEC(dnsdistsettings::DNSSECSelectorConfiguration),
+ DSTPort(dnsdistsettings::DSTPortSelectorConfiguration),
+ EDNSOption(dnsdistsettings::EDNSOptionSelectorConfiguration),
+ EDNSVersion(dnsdistsettings::EDNSVersionSelectorConfiguration),
+ ERCode(dnsdistsettings::ERCodeSelectorConfiguration),
+ HTTPHeader(dnsdistsettings::HTTPHeaderSelectorConfiguration),
+ HTTPPath(dnsdistsettings::HTTPPathSelectorConfiguration),
+ HTTPPathRegex(dnsdistsettings::HTTPPathRegexSelectorConfiguration),
+ KeyValueStoreLookup(dnsdistsettings::KeyValueStoreLookupSelectorConfiguration),
+ KeyValueStoreRangeLookup(dnsdistsettings::KeyValueStoreRangeLookupSelectorConfiguration),
+ Lua(dnsdistsettings::LuaSelectorConfiguration),
+ LuaFFI(dnsdistsettings::LuaFFISelectorConfiguration),
+ LuaFFIPerThread(dnsdistsettings::LuaFFIPerThreadSelectorConfiguration),
+ MaxQPS(dnsdistsettings::MaxQPSSelectorConfiguration),
+ MaxQPSIP(dnsdistsettings::MaxQPSIPSelectorConfiguration),
+ NetmaskGroup(dnsdistsettings::NetmaskGroupSelectorConfiguration),
+ Not(NotSelectorConfigurationSerde),
+ Opcode(dnsdistsettings::OpcodeSelectorConfiguration),
+ Or(OrSelectorConfigurationSerde),
+ PayloadSize(dnsdistsettings::PayloadSizeSelectorConfiguration),
+ PoolAvailable(dnsdistsettings::PoolAvailableSelectorConfiguration),
+ PoolOutstanding(dnsdistsettings::PoolOutstandingSelectorConfiguration),
+ Proba(dnsdistsettings::ProbaSelectorConfiguration),
+ ProxyProtocolValue(dnsdistsettings::ProxyProtocolValueSelectorConfiguration),
+ QClass(dnsdistsettings::QClassSelectorConfiguration),
+ QName(dnsdistsettings::QNameSelectorConfiguration),
+ QNameLabelsCount(dnsdistsettings::QNameLabelsCountSelectorConfiguration),
+ QNameSet(dnsdistsettings::QNameSetSelectorConfiguration),
+ QNameSuffix(dnsdistsettings::QNameSuffixSelectorConfiguration),
+ QNameWireLength(dnsdistsettings::QNameWireLengthSelectorConfiguration),
+ QType(dnsdistsettings::QTypeSelectorConfiguration),
+ RCode(dnsdistsettings::RCodeSelectorConfiguration),
+ RD(dnsdistsettings::RDSelectorConfiguration),
+ RE2(dnsdistsettings::RE2SelectorConfiguration),
+ RecordsCount(dnsdistsettings::RecordsCountSelectorConfiguration),
+ RecordsTypeCount(dnsdistsettings::RecordsTypeCountSelectorConfiguration),
+ Regex(dnsdistsettings::RegexSelectorConfiguration),
+ SNI(dnsdistsettings::SNISelectorConfiguration),
+ Tag(dnsdistsettings::TagSelectorConfiguration),
+ TCP(dnsdistsettings::TCPSelectorConfiguration),
+ TrailingData(dnsdistsettings::TrailingDataSelectorConfiguration),
+}
+
+impl Default for dnsdistsettings::MetricsConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::MetricsConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::CarbonConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::CarbonConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::RemoteLoggingConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::RemoteLoggingConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::ProtobufLoggerConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::ProtobufLoggerConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::DnstapLoggerConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::DnstapLoggerConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::ProtoBufMetaConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::ProtoBufMetaConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::LMDBKVStoreConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::LMDBKVStoreConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::CDBKVStoreConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::CDBKVStoreConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KVSLookupKeySourceIPConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KVSLookupKeySourceIPConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KVSLookupKeyQNameConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KVSLookupKeyQNameConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KVSLookupKeySuffixConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KVSLookupKeySuffixConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KVSLookupKeyTagConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KVSLookupKeyTagConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KVSLookupKeysConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KVSLookupKeysConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::KeyValueStoresConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::KeyValueStoresConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::WebserverConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::WebserverConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::ConsoleConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::ConsoleConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::EdnsClientSubnetConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::EdnsClientSubnetConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for dynamic_rules_settings_default_action
+fn default_value_dynamic_rules_settings_default_action() -> String {
+ String::from("Drop")
+}
+fn default_value_equal_dynamic_rules_settings_default_action(value: &str)-> bool {
+ value == default_value_dynamic_rules_settings_default_action()
+}
+
+
+impl Default for dnsdistsettings::DynamicRulesSettingsConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::DynamicRulesSettingsConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for dynamic_rule_action
+fn default_value_dynamic_rule_action() -> String {
+ String::from("drop")
+}
+fn default_value_equal_dynamic_rule_action(value: &str)-> bool {
+ value == default_value_dynamic_rule_action()
+}
+
+
+// DEFAULT HANDLING for dynamic_rule_tag_value
+fn default_value_dynamic_rule_tag_value() -> String {
+ String::from("0")
+}
+fn default_value_equal_dynamic_rule_tag_value(value: &str)-> bool {
+ value == default_value_dynamic_rule_tag_value()
+}
+
+
+impl Default for dnsdistsettings::DynamicRuleConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::DynamicRuleConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::DynamicRulesConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::DynamicRulesConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::RingBuffersConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::RingBuffersConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::IncomingTlsCertificateKeyPairConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingTlsCertificateKeyPairConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for incoming_tls_provider
+fn default_value_incoming_tls_provider() -> String {
+ String::from("OpenSSL")
+}
+fn default_value_equal_incoming_tls_provider(value: &str)-> bool {
+ value == default_value_incoming_tls_provider()
+}
+
+
+// DEFAULT HANDLING for incoming_tls_minimum_version
+fn default_value_incoming_tls_minimum_version() -> String {
+ String::from("tls1.0")
+}
+fn default_value_equal_incoming_tls_minimum_version(value: &str)-> bool {
+ value == default_value_incoming_tls_minimum_version()
+}
+
+
+impl Default for dnsdistsettings::IncomingTlsConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingTlsConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for outgoing_tls_provider
+fn default_value_outgoing_tls_provider() -> String {
+ String::from("OpenSSL")
+}
+fn default_value_equal_outgoing_tls_provider(value: &str)-> bool {
+ value == default_value_outgoing_tls_provider()
+}
+
+
+impl Default for dnsdistsettings::OutgoingTlsConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::OutgoingTlsConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::HttpCustomResponseHeaderConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::HttpCustomResponseHeaderConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::HttpResponsesMapConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::HttpResponsesMapConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for incoming_doh_provider
+fn default_value_incoming_doh_provider() -> String {
+ String::from("nghttp2")
+}
+fn default_value_equal_incoming_doh_provider(value: &str)-> bool {
+ value == default_value_incoming_doh_provider()
+}
+
+
+// DEFAULT HANDLING for incoming_doh_server_tokens
+fn default_value_incoming_doh_server_tokens() -> String {
+ String::from("h2o/dnsdist")
+}
+fn default_value_equal_incoming_doh_server_tokens(value: &str)-> bool {
+ value == default_value_incoming_doh_server_tokens()
+}
+
+
+impl Default for dnsdistsettings::IncomingDohConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingDohConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::IncomingDoqConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingDoqConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for incoming_quic_congestion_control_algorithm
+fn default_value_incoming_quic_congestion_control_algorithm() -> String {
+ String::from("reno")
+}
+fn default_value_equal_incoming_quic_congestion_control_algorithm(value: &str)-> bool {
+ value == default_value_incoming_quic_congestion_control_algorithm()
+}
+
+
+impl Default for dnsdistsettings::IncomingQuicConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingQuicConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for outgoing_doh_path
+fn default_value_outgoing_doh_path() -> String {
+ String::from("/dns-query")
+}
+fn default_value_equal_outgoing_doh_path(value: &str)-> bool {
+ value == default_value_outgoing_doh_path()
+}
+
+
+impl Default for dnsdistsettings::OutgoingDohConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::OutgoingDohConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::IncomingTcpConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::IncomingTcpConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for bind_protocol
+fn default_value_bind_protocol() -> String {
+ String::from("Do53")
+}
+fn default_value_equal_bind_protocol(value: &str)-> bool {
+ value == default_value_bind_protocol()
+}
+
+
+impl Default for dnsdistsettings::BindConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::BindConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::OutgoingTcpConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::OutgoingTcpConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::ProxyProtocolValueConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::ProxyProtocolValueConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for lazy_health_check_mode
+fn default_value_lazy_health_check_mode() -> String {
+ String::from("TimeoutOrServFail")
+}
+fn default_value_equal_lazy_health_check_mode(value: &str)-> bool {
+ value == default_value_lazy_health_check_mode()
+}
+
+
+impl Default for dnsdistsettings::LazyHealthCheckConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::LazyHealthCheckConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for health_check_mode
+fn default_value_health_check_mode() -> String {
+ String::from("auto")
+}
+fn default_value_equal_health_check_mode(value: &str)-> bool {
+ value == default_value_health_check_mode()
+}
+
+
+// DEFAULT HANDLING for health_check_qclass
+fn default_value_health_check_qclass() -> String {
+ String::from("IN")
+}
+fn default_value_equal_health_check_qclass(value: &str)-> bool {
+ value == default_value_health_check_qclass()
+}
+
+
+// DEFAULT HANDLING for health_check_qtype
+fn default_value_health_check_qtype() -> String {
+ String::from("A")
+}
+fn default_value_equal_health_check_qtype(value: &str)-> bool {
+ value == default_value_health_check_qtype()
+}
+
+
+impl Default for dnsdistsettings::HealthCheckConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::HealthCheckConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::OutgoingAutoUpgradeConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::OutgoingAutoUpgradeConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::BackendConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::BackendConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::TuningConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::TuningConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::TcpTuningConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::TcpTuningConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::UdpTuningConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::UdpTuningConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::TlsTuningConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::TlsTuningConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::DohTuningConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::DohTuningConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::CacheSettingsConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::CacheSettingsConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for security_polling_suffix
+fn default_value_security_polling_suffix() -> String {
+ String::from("secpoll.powerdns.com.")
+}
+fn default_value_equal_security_polling_suffix(value: &str)-> bool {
+ value == default_value_security_polling_suffix()
+}
+
+
+impl Default for dnsdistsettings::SecurityPollingConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::SecurityPollingConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::GeneralConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::GeneralConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::PacketCacheConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::PacketCacheConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::ProxyProtocolConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::ProxyProtocolConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::SnmpConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::SnmpConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::QueryCountConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::QueryCountConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+// DEFAULT HANDLING for pool_policy
+fn default_value_pool_policy() -> String {
+ String::from("least-outstanding")
+}
+fn default_value_equal_pool_policy(value: &str)-> bool {
+ value == default_value_pool_policy()
+}
+
+
+impl Default for dnsdistsettings::PoolConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::PoolConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::CustomLoadBalancingPolicyConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::CustomLoadBalancingPolicyConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for dnsdistsettings::LoadBalancingPoliciesConfiguration {
+ fn default() -> Self {
+ let deserialized: dnsdistsettings::LoadBalancingPoliciesConfiguration = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl Default for GlobalConfigurationSerde {
+ fn default() -> Self {
+ let deserialized: GlobalConfigurationSerde = serde_yaml::from_str("").unwrap();
+ deserialized
+ }
+}
+
+
+impl dnsdistsettings::GlobalConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.backends {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.binds {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_hit_response_rules {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_inserted_response_rules {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_miss_rules {
+ sub_type.validate()?;
+ }
+ self.cache_settings.validate()?;
+ self.console.validate()?;
+ for sub_type in &self.dynamic_rules {
+ sub_type.validate()?;
+ }
+ self.dynamic_rules_settings.validate()?;
+ self.edns_client_subnet.validate()?;
+ self.general.validate()?;
+ self.key_value_stores.validate()?;
+ self.load_balancing_policies.validate()?;
+ self.metrics.validate()?;
+ for sub_type in &self.packet_caches {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.pools {
+ sub_type.validate()?;
+ }
+ self.proxy_protocol.validate()?;
+ self.query_count.validate()?;
+ for sub_type in &self.query_rules {
+ sub_type.validate()?;
+ }
+ self.remote_logging.validate()?;
+ for sub_type in &self.response_rules {
+ sub_type.validate()?;
+ }
+ self.ring_buffers.validate()?;
+ self.security_polling.validate()?;
+ for sub_type in &self.self_answered_response_rules {
+ sub_type.validate()?;
+ }
+ self.snmp.validate()?;
+ self.tuning.validate()?;
+ self.webserver.validate()?;
+ for sub_type in &self.xfr_response_rules {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::MetricsConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.carbon {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::CarbonConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::RemoteLoggingConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.protobuf_loggers {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.dnstap_loggers {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::ProtobufLoggerConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::DnstapLoggerConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::ProtoBufMetaConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::LMDBKVStoreConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::CDBKVStoreConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::KVSLookupKeySourceIPConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::KVSLookupKeyQNameConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::KVSLookupKeySuffixConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::KVSLookupKeyTagConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::KVSLookupKeysConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.source_ip_keys {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.qname_keys {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.suffix_keys {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.tag_keys {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::KeyValueStoresConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.lmdb {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cdb {
+ sub_type.validate()?;
+ }
+ self.lookup_keys.validate()?;
+ Ok(())
+ }
+}
+impl dnsdistsettings::WebserverConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.custom_headers {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::ConsoleConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::EdnsClientSubnetConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::DynamicRulesSettingsConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::DynamicRuleConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::DynamicRulesConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.rules {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::RingBuffersConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingTlsCertificateKeyPairConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingTlsConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.certificates {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::OutgoingTlsConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::HttpCustomResponseHeaderConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::HttpResponsesMapConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.headers {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingDohConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.custom_response_headers {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.responses_map {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingDoqConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingQuicConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::OutgoingDohConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::IncomingTcpConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::BindConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ self.tcp.validate()?;
+ self.tls.validate()?;
+ self.doh.validate()?;
+ self.doq.validate()?;
+ self.quic.validate()?;
+ Ok(())
+ }
+}
+impl dnsdistsettings::OutgoingTcpConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::ProxyProtocolValueConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::LazyHealthCheckConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::HealthCheckConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ self.lazy.validate()?;
+ Ok(())
+ }
+}
+impl dnsdistsettings::OutgoingAutoUpgradeConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::BackendConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ self.tls.validate()?;
+ self.doh.validate()?;
+ self.tcp.validate()?;
+ self.health_checks.validate()?;
+ self.auto_upgrade.validate()?;
+ Ok(())
+ }
+}
+impl dnsdistsettings::TuningConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ self.doh.validate()?;
+ self.tcp.validate()?;
+ self.tls.validate()?;
+ self.udp.validate()?;
+ Ok(())
+ }
+}
+impl dnsdistsettings::TcpTuningConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::UdpTuningConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::TlsTuningConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::DohTuningConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::CacheSettingsConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::SecurityPollingConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::GeneralConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::PacketCacheConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::ProxyProtocolConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::SnmpConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::QueryCountConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::PoolConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::CustomLoadBalancingPolicyConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::LoadBalancingPoliciesConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.custom_policies {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+impl dnsdistsettings::QueryRuleConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ Ok(())
+ }
+}
+impl dnsdistsettings::ResponseRuleConfiguration {
+ fn validate(&self) -> Result<(), ValidationError> {
+ self.action.validate()?;
+ Ok(())
+ }
+}
+impl GlobalConfigurationSerde {
+ fn validate(&self) -> Result<(), ValidationError> {
+ for sub_type in &self.backends {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.binds {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_hit_response_rules {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_inserted_response_rules {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.cache_miss_rules {
+ sub_type.validate()?;
+ }
+ self.cache_settings.validate()?;
+ self.console.validate()?;
+ for sub_type in &self.dynamic_rules {
+ sub_type.validate()?;
+ }
+ self.dynamic_rules_settings.validate()?;
+ self.edns_client_subnet.validate()?;
+ self.general.validate()?;
+ self.key_value_stores.validate()?;
+ self.load_balancing_policies.validate()?;
+ self.metrics.validate()?;
+ for sub_type in &self.packet_caches {
+ sub_type.validate()?;
+ }
+ for sub_type in &self.pools {
+ sub_type.validate()?;
+ }
+ self.proxy_protocol.validate()?;
+ self.query_count.validate()?;
+ for sub_type in &self.query_rules {
+ sub_type.validate()?;
+ }
+ self.remote_logging.validate()?;
+ for sub_type in &self.response_rules {
+ sub_type.validate()?;
+ }
+ self.ring_buffers.validate()?;
+ self.security_polling.validate()?;
+ for sub_type in &self.self_answered_response_rules {
+ sub_type.validate()?;
+ }
+ self.snmp.validate()?;
+ self.tuning.validate()?;
+ self.webserver.validate()?;
+ for sub_type in &self.xfr_response_rules {
+ sub_type.validate()?;
+ }
+ Ok(())
+ }
+}
+fn get_one_action_from_serde(action: &Action) -> Option<dnsdistsettings::SharedDNSAction> {
+ match action {
+ Action::Default => {}
+ Action::Allow(config) => {
+ let tmp_action = dnsdistsettings::getAllowAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Continue(cont) => {
+ let mut config: dnsdistsettings::ContinueActionConfiguration = Default::default();
+ let new_action = get_one_action_from_serde(&*cont.action);
+ if new_action.is_some() {
+ config.action = new_action.unwrap();
+ }
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: dnsdistsettings::getContinueAction(&config),
+ });
+ }
+ Action::Delay(config) => {
+ let tmp_action = dnsdistsettings::getDelayAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::DnstapLog(config) => {
+ let tmp_action = dnsdistsettings::getDnstapLogAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Drop(config) => {
+ let tmp_action = dnsdistsettings::getDropAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetEDNSOption(config) => {
+ let tmp_action = dnsdistsettings::getSetEDNSOptionAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::ERCode(config) => {
+ let tmp_action = dnsdistsettings::getERCodeAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::HTTPStatus(config) => {
+ let tmp_action = dnsdistsettings::getHTTPStatusAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::KeyValueStoreLookup(config) => {
+ let tmp_action = dnsdistsettings::getKeyValueStoreLookupAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::KeyValueStoreRangeLookup(config) => {
+ let tmp_action = dnsdistsettings::getKeyValueStoreRangeLookupAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Log(config) => {
+ let tmp_action = dnsdistsettings::getLogAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Lua(config) => {
+ let tmp_action = dnsdistsettings::getLuaAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::LuaFFI(config) => {
+ let tmp_action = dnsdistsettings::getLuaFFIAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::LuaFFIPerThread(config) => {
+ let tmp_action = dnsdistsettings::getLuaFFIPerThreadAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::NegativeAndSOA(config) => {
+ let tmp_action = dnsdistsettings::getNegativeAndSOAAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::None(config) => {
+ let tmp_action = dnsdistsettings::getNoneAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Pool(config) => {
+ let tmp_action = dnsdistsettings::getPoolAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::QPS(config) => {
+ let tmp_action = dnsdistsettings::getQPSAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::QPSPool(config) => {
+ let tmp_action = dnsdistsettings::getQPSPoolAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::RCode(config) => {
+ let tmp_action = dnsdistsettings::getRCodeAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::RemoteLog(config) => {
+ let tmp_action = dnsdistsettings::getRemoteLogAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetAdditionalProxyProtocolValue(config) => {
+ let tmp_action = dnsdistsettings::getSetAdditionalProxyProtocolValueAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetDisableECS(config) => {
+ let tmp_action = dnsdistsettings::getSetDisableECSAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetDisableValidation(config) => {
+ let tmp_action = dnsdistsettings::getSetDisableValidationAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetECS(config) => {
+ let tmp_action = dnsdistsettings::getSetECSAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetECSOverride(config) => {
+ let tmp_action = dnsdistsettings::getSetECSOverrideAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetECSPrefixLength(config) => {
+ let tmp_action = dnsdistsettings::getSetECSPrefixLengthAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetExtendedDNSError(config) => {
+ let tmp_action = dnsdistsettings::getSetExtendedDNSErrorAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetMacAddr(config) => {
+ let tmp_action = dnsdistsettings::getSetMacAddrAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetMaxReturnedTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetMaxReturnedTTLAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetNoRecurse(config) => {
+ let tmp_action = dnsdistsettings::getSetNoRecurseAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetProxyProtocolValues(config) => {
+ let tmp_action = dnsdistsettings::getSetProxyProtocolValuesAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetSkipCache(config) => {
+ let tmp_action = dnsdistsettings::getSetSkipCacheAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetTag(config) => {
+ let tmp_action = dnsdistsettings::getSetTagAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SetTempFailureCacheTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetTempFailureCacheTTLAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SNMPTrap(config) => {
+ let tmp_action = dnsdistsettings::getSNMPTrapAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Spoof(config) => {
+ let tmp_action = dnsdistsettings::getSpoofAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SpoofCNAME(config) => {
+ let tmp_action = dnsdistsettings::getSpoofCNAMEAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SpoofPacket(config) => {
+ let tmp_action = dnsdistsettings::getSpoofPacketAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SpoofRaw(config) => {
+ let tmp_action = dnsdistsettings::getSpoofRawAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::SpoofSVC(config) => {
+ let tmp_action = dnsdistsettings::getSpoofSVCAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::TC(config) => {
+ let tmp_action = dnsdistsettings::getTCAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ Action::Tee(config) => {
+ let tmp_action = dnsdistsettings::getTeeAction(&config);
+ return Some(dnsdistsettings::SharedDNSAction {
+ action: tmp_action,
+ });
+ }
+ }
+ None
+}
+fn get_one_response_action_from_serde(action: &ResponseAction) -> Option<dnsdistsettings::SharedDNSResponseAction> {
+ match action {
+ ResponseAction::Default => {}
+ ResponseAction::Allow(config) => {
+ let tmp_action = dnsdistsettings::getAllowResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::ClearRecordTypes(config) => {
+ let tmp_action = dnsdistsettings::getClearRecordTypesResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::Delay(config) => {
+ let tmp_action = dnsdistsettings::getDelayResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::DnstapLog(config) => {
+ let tmp_action = dnsdistsettings::getDnstapLogResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::Drop(config) => {
+ let tmp_action = dnsdistsettings::getDropResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::LimitTTL(config) => {
+ let tmp_action = dnsdistsettings::getLimitTTLResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::Log(config) => {
+ let tmp_action = dnsdistsettings::getLogResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::Lua(config) => {
+ let tmp_action = dnsdistsettings::getLuaResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::LuaFFI(config) => {
+ let tmp_action = dnsdistsettings::getLuaFFIResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::LuaFFIPerThread(config) => {
+ let tmp_action = dnsdistsettings::getLuaFFIPerThreadResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::RemoteLog(config) => {
+ let tmp_action = dnsdistsettings::getRemoteLogResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetExtendedDNSError(config) => {
+ let tmp_action = dnsdistsettings::getSetExtendedDNSErrorResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetMaxReturnedTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetMaxReturnedTTLResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetMaxTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetMaxTTLResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetMinTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetMinTTLResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetReducedTTL(config) => {
+ let tmp_action = dnsdistsettings::getSetReducedTTLResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetSkipCache(config) => {
+ let tmp_action = dnsdistsettings::getSetSkipCacheResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SetTag(config) => {
+ let tmp_action = dnsdistsettings::getSetTagResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::SNMPTrap(config) => {
+ let tmp_action = dnsdistsettings::getSNMPTrapResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ ResponseAction::TC(config) => {
+ let tmp_action = dnsdistsettings::getTCResponseAction(&config);
+ return Some(dnsdistsettings::SharedDNSResponseAction {
+ action: tmp_action,
+ });
+ }
+ }
+ None
+}
+fn get_one_selector_from_serde(selector: &Selector) -> Option<dnsdistsettings::SharedDNSSelector> {
+ match selector {
+ Selector::Default => {}
+ Selector::All(all) => {
+ let tmp_selector = dnsdistsettings::getAllSelector(&all);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::And(and) => {
+ let mut config: dnsdistsettings::AndSelectorConfiguration = Default::default();
+ for sub_selector in &and.selectors {
+ let new_selector = get_one_selector_from_serde(&sub_selector);
+ if new_selector.is_some() {
+ config.selectors.push(new_selector.unwrap());
+ }
+ }
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: dnsdistsettings::getAndSelector(&config),
+ });
+ }
+ Selector::ByName(byname) => {
+ let tmp_selector = dnsdistsettings::getByNameSelector(&byname);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::DNSSEC(dnssec) => {
+ let tmp_selector = dnsdistsettings::getDNSSECSelector(&dnssec);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::DSTPort(dstport) => {
+ let tmp_selector = dnsdistsettings::getDSTPortSelector(&dstport);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::EDNSOption(ednsoption) => {
+ let tmp_selector = dnsdistsettings::getEDNSOptionSelector(&ednsoption);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::EDNSVersion(ednsversion) => {
+ let tmp_selector = dnsdistsettings::getEDNSVersionSelector(&ednsversion);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::ERCode(ercode) => {
+ let tmp_selector = dnsdistsettings::getERCodeSelector(&ercode);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::HTTPHeader(httpheader) => {
+ let tmp_selector = dnsdistsettings::getHTTPHeaderSelector(&httpheader);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::HTTPPath(httppath) => {
+ let tmp_selector = dnsdistsettings::getHTTPPathSelector(&httppath);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::HTTPPathRegex(httppathregex) => {
+ let tmp_selector = dnsdistsettings::getHTTPPathRegexSelector(&httppathregex);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::KeyValueStoreLookup(keyvaluestorelookup) => {
+ let tmp_selector = dnsdistsettings::getKeyValueStoreLookupSelector(&keyvaluestorelookup);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::KeyValueStoreRangeLookup(keyvaluestorerangelookup) => {
+ let tmp_selector = dnsdistsettings::getKeyValueStoreRangeLookupSelector(&keyvaluestorerangelookup);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Lua(lua) => {
+ let tmp_selector = dnsdistsettings::getLuaSelector(&lua);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::LuaFFI(luaffi) => {
+ let tmp_selector = dnsdistsettings::getLuaFFISelector(&luaffi);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::LuaFFIPerThread(luaffiperthread) => {
+ let tmp_selector = dnsdistsettings::getLuaFFIPerThreadSelector(&luaffiperthread);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::MaxQPS(maxqps) => {
+ let tmp_selector = dnsdistsettings::getMaxQPSSelector(&maxqps);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::MaxQPSIP(maxqpsip) => {
+ let tmp_selector = dnsdistsettings::getMaxQPSIPSelector(&maxqpsip);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::NetmaskGroup(netmaskgroup) => {
+ let tmp_selector = dnsdistsettings::getNetmaskGroupSelector(&netmaskgroup);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Not(not) => {
+ let mut config: dnsdistsettings::NotSelectorConfiguration = Default::default();
+ let new_selector = get_one_selector_from_serde(&*not.selector);
+ if new_selector.is_some() {
+ config.selector = new_selector.unwrap();
+ }
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: dnsdistsettings::getNotSelector(&config),
+ });
+ }
+ Selector::Opcode(opcode) => {
+ let tmp_selector = dnsdistsettings::getOpcodeSelector(&opcode);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Or(or) => {
+ let mut config: dnsdistsettings::OrSelectorConfiguration = Default::default();
+ for sub_selector in &or.selectors {
+ let new_selector = get_one_selector_from_serde(&sub_selector);
+ if new_selector.is_some() {
+ config.selectors.push(new_selector.unwrap());
+ }
+ }
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: dnsdistsettings::getOrSelector(&config),
+ });
+ }
+ Selector::PayloadSize(payloadsize) => {
+ let tmp_selector = dnsdistsettings::getPayloadSizeSelector(&payloadsize);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::PoolAvailable(poolavailable) => {
+ let tmp_selector = dnsdistsettings::getPoolAvailableSelector(&poolavailable);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::PoolOutstanding(pooloutstanding) => {
+ let tmp_selector = dnsdistsettings::getPoolOutstandingSelector(&pooloutstanding);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Proba(proba) => {
+ let tmp_selector = dnsdistsettings::getProbaSelector(&proba);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::ProxyProtocolValue(proxyprotocolvalue) => {
+ let tmp_selector = dnsdistsettings::getProxyProtocolValueSelector(&proxyprotocolvalue);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QClass(qclass) => {
+ let tmp_selector = dnsdistsettings::getQClassSelector(&qclass);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QName(qname) => {
+ let tmp_selector = dnsdistsettings::getQNameSelector(&qname);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QNameLabelsCount(qnamelabelscount) => {
+ let tmp_selector = dnsdistsettings::getQNameLabelsCountSelector(&qnamelabelscount);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QNameSet(qnameset) => {
+ let tmp_selector = dnsdistsettings::getQNameSetSelector(&qnameset);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QNameSuffix(qnamesuffix) => {
+ let tmp_selector = dnsdistsettings::getQNameSuffixSelector(&qnamesuffix);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QNameWireLength(qnamewirelength) => {
+ let tmp_selector = dnsdistsettings::getQNameWireLengthSelector(&qnamewirelength);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::QType(qtype) => {
+ let tmp_selector = dnsdistsettings::getQTypeSelector(&qtype);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::RCode(rcode) => {
+ let tmp_selector = dnsdistsettings::getRCodeSelector(&rcode);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::RD(rd) => {
+ let tmp_selector = dnsdistsettings::getRDSelector(&rd);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::RE2(re2) => {
+ let tmp_selector = dnsdistsettings::getRE2Selector(&re2);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::RecordsCount(recordscount) => {
+ let tmp_selector = dnsdistsettings::getRecordsCountSelector(&recordscount);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::RecordsTypeCount(recordstypecount) => {
+ let tmp_selector = dnsdistsettings::getRecordsTypeCountSelector(&recordstypecount);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Regex(regex) => {
+ let tmp_selector = dnsdistsettings::getRegexSelector(®ex);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::SNI(sni) => {
+ let tmp_selector = dnsdistsettings::getSNISelector(&sni);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::Tag(tag) => {
+ let tmp_selector = dnsdistsettings::getTagSelector(&tag);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::TCP(tcp) => {
+ let tmp_selector = dnsdistsettings::getTCPSelector(&tcp);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ Selector::TrailingData(trailingdata) => {
+ let tmp_selector = dnsdistsettings::getTrailingDataSelector(&trailingdata);
+ return Some(dnsdistsettings::SharedDNSSelector {
+ selector: tmp_selector,
+ });
+ }
+ }
+ None
+}
+// START INCLUDE ./rust-post-in.rs
+fn get_selectors_from_serde(
+ selectors_from_serde: &Vec<Selector>,
+) -> Vec<dnsdistsettings::SharedDNSSelector> {
+ let mut results: Vec<dnsdistsettings::SharedDNSSelector> = Vec::new();
+
+ for rule in selectors_from_serde {
+ let selector = get_one_selector_from_serde(&rule);
+ if selector.is_some() {
+ results.push(selector.unwrap());
+ }
+ }
+ results
+}
+
+fn get_query_rules_from_serde(
+ rules_from_serde: &Vec<QueryRuleConfigurationSerde>,
+) -> Vec<dnsdistsettings::QueryRuleConfiguration> {
+ let mut results: Vec<dnsdistsettings::QueryRuleConfiguration> = Vec::new();
+
+ for rule in rules_from_serde {
+ let selector = get_one_selector_from_serde(&rule.selector);
+ let action = get_one_action_from_serde(&rule.action);
+ if selector.is_some() && action.is_some() {
+ results.push(dnsdistsettings::QueryRuleConfiguration {
+ name: rule.name.clone(),
+ uuid: rule.uuid.clone(),
+ selector: selector.unwrap(),
+ action: action.unwrap(),
+ });
+ }
+ }
+ results
+}
+
+fn get_response_rules_from_serde(
+ rules_from_serde: &Vec<ResponseRuleConfigurationSerde>,
+) -> Vec<dnsdistsettings::ResponseRuleConfiguration> {
+ let mut results: Vec<dnsdistsettings::ResponseRuleConfiguration> = Vec::new();
+
+ for rule in rules_from_serde {
+ let selector = get_one_selector_from_serde(&rule.selector);
+ let action = get_one_response_action_from_serde(&rule.action);
+ if selector.is_some() && action.is_some() {
+ results.push(dnsdistsettings::ResponseRuleConfiguration {
+ name: rule.name.clone(),
+ uuid: rule.uuid.clone(),
+ selector: selector.unwrap(),
+ action: action.unwrap(),
+ });
+ }
+ }
+ results
+}
+
+fn register_remote_loggers(
+ config: &dnsdistsettings::RemoteLoggingConfiguration,
+) {
+ for logger in &config.protobuf_loggers {
+ dnsdistsettings::registerProtobufLogger(&logger);
+ }
+ for logger in &config.dnstap_loggers {
+ dnsdistsettings::registerDnstapLogger(&logger);
+ }
+}
+
+fn get_global_configuration_from_serde(
+ serde: GlobalConfigurationSerde,
+) -> dnsdistsettings::GlobalConfiguration {
+ let mut config: dnsdistsettings::GlobalConfiguration = Default::default();
+ config.key_value_stores = serde.key_value_stores;
+ config.webserver = serde.webserver;
+ config.console = serde.console;
+ config.edns_client_subnet = serde.edns_client_subnet;
+ config.dynamic_rules_settings = serde.dynamic_rules_settings;
+ config.dynamic_rules = serde.dynamic_rules;
+ config.acl = serde.acl;
+ config.ring_buffers = serde.ring_buffers;
+ config.binds = serde.binds;
+ config.backends = serde.backends;
+ config.cache_settings = serde.cache_settings;
+ config.security_polling = serde.security_polling;
+ config.general = serde.general;
+ config.packet_caches = serde.packet_caches;
+ config.proxy_protocol = serde.proxy_protocol;
+ config.snmp = serde.snmp;
+ config.query_count = serde.query_count;
+ config.load_balancing_policies = serde.load_balancing_policies;
+ config.pools = serde.pools;
+ config.metrics = serde.metrics;
+ config.remote_logging = serde.remote_logging;
+ config.tuning = serde.tuning;
+ // this needs to be done before the rules so that they can refer to the loggers
+ register_remote_loggers(&config.remote_logging);
+ // this needs to be done before the rules so that they can refer to the KVS objects
+ dnsdistsettings::registerKVSObjects(&config.key_value_stores);
+ // this needs to be done BEFORE the rules so that they can refer to the selectors
+ // by name
+ config.selectors = get_selectors_from_serde(&serde.selectors);
+ config.query_rules = get_query_rules_from_serde(&serde.query_rules);
+ config.cache_miss_rules = get_query_rules_from_serde(&serde.cache_miss_rules);
+ config.response_rules = get_response_rules_from_serde(&serde.response_rules);
+ config.cache_hit_response_rules = get_response_rules_from_serde(&serde.cache_hit_response_rules);
+ config.cache_inserted_response_rules = get_response_rules_from_serde(&serde.cache_inserted_response_rules);
+ config.self_answered_response_rules = get_response_rules_from_serde(&serde.self_answered_response_rules);
+ config.xfr_response_rules = get_response_rules_from_serde(&serde.xfr_response_rules);
+ config
+}
+
+pub fn from_yaml_string(
+ str: &str,
+) -> Result<dnsdistsettings::GlobalConfiguration, serde_yaml::Error> {
+ let serde_config: Result<GlobalConfigurationSerde, serde_yaml::Error> =
+ serde_yaml::from_str(str);
+
+ if !serde_config.is_err() {
+ let validation_result = serde_config.as_ref().unwrap().validate();
+ if let Err(e) = validation_result {
+ println!("Error validating the configuration loaded from {}: {}", str, e);
+ }
}
+ let config: dnsdistsettings::GlobalConfiguration =
+ get_global_configuration_from_serde(serde_config?);
+ return Ok(config);
}
+// END INCLUDE ./rust-post-in.rs