From: Remi Gacogne Date: Tue, 24 Dec 2024 15:53:19 +0000 (+0100) Subject: dnsdist: Add yaml configuration X-Git-Tag: dnsdist-2.0.0-alpha1~160^2~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bc4b1be1f24f593d1d67fa517cf25f064683e565;p=thirdparty%2Fpdns.git dnsdist: Add yaml configuration --- diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 3051932f08..c1507b80b7 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -117,6 +117,7 @@ EXTRA_DIST=COPYING \ dnsdist-rust-bridge-selectors-generated.cc \ dnsdist-rust-bridge-selectors-generated.hh \ dnsdist-selectors-definitions.yml \ + dnsdist-settings-definitions.yml \ dnslabeltext.rl \ dnsdist.conf-dist \ dnsmessage.proto \ @@ -180,6 +181,8 @@ dnsdist_SOURCES = \ dnsdist-cache.cc dnsdist-cache.hh \ dnsdist-carbon.cc dnsdist-carbon.hh \ dnsdist-concurrent-connections.hh \ + dnsdist-configuration-yaml-internal.hh \ + dnsdist-configuration-yaml.cc dnsdist-configuration-yaml.hh \ dnsdist-configuration.cc dnsdist-configuration.hh \ dnsdist-console.cc dnsdist-console.hh \ dnsdist-crypto.cc dnsdist-crypto.hh \ @@ -526,6 +529,7 @@ testrunner_LDADD += $(QUICHE_LDFLAGS) $(QUICHE_LIBS) endif if HAVE_YAML_CONFIGURATION +dnsdist_SOURCES += dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated.cc dnsdist_LDADD += $(DNSDIST_RUST_LIBS) endif diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml-internal.hh b/pdns/dnsdistdist/dnsdist-configuration-yaml-internal.hh new file mode 100644 index 0000000000..bbae2cd7a6 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml-internal.hh @@ -0,0 +1,32 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include "dnsdist-configuration.hh" + +namespace dnsdist::configuration::yaml +{ +#if defined(HAVE_YAML_CONFIGURATION) +void convertImmutableFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::ImmutableConfiguration& config); +void convertRuntimeFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::RuntimeConfiguration& config); +#endif /* HAVE_YAML_CONFIGURATION */ +} diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.cc b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc new file mode 100644 index 0000000000..4f91015545 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.cc @@ -0,0 +1,1381 @@ +/* + * 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 + +#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 +#endif /* HAVE_YAML_CONFIGURATION */ + +namespace dnsdist::configuration::yaml +{ +#if defined(HAVE_YAML_CONFIGURATION) + +using RegisteredTypes = std::variant, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr>; +static LockGuarded> s_registeredTypesMap; +static std::atomic s_inConfigCheckMode; +static std::atomic s_inClientMode; + +template +static void registerType(const std::shared_ptr& 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 +static std::shared_ptr 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>(&item->second)) { + return *ptr; + } + return nullptr; +} + +template +static std::shared_ptr getRegisteredTypeByName(const ::rust::String& name) +{ + auto nameStr = std::string(name); + return getRegisteredTypeByName(nameStr); +} + +template +static T checkedConversionFromStr(const std::string& context, const std::string& parameterName, const std::string& str) +{ + try { + return pdns::checked_stoi(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 +static T checkedConversionFromStr(const std::string& context, const std::string& parameterName, const ::rust::string& str) +{ + return checkedConversionFromStr(context, parameterName, std::string(str)); +} + +static std::set getCPUPiningFromStr(const std::string& context, const std::string& cpuStr) +{ + std::set cpus; + std::vector tokens; + stringtok(tokens, cpuStr); + for (const auto& token : tokens) { + cpus.insert(checkedConversionFromStr(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 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::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(); + 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(); + 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(); + 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(); + // 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>>(); + for (const auto& responsesMap : bind.doh.responses_map) { + boost::optional> headers; + if (!responsesMap.headers.empty()) { + headers = std::unordered_map(); + 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(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 +static bool getOptionalLuaFunction(T& destination, const ::rust::string& functionName) +{ + auto lua = g_lua.lock(); + auto function = lua->readVariable>(std::string(functionName)); + if (!function) { + return false; + } + destination = *function; + return true; +} + +static std::shared_ptr createBackendFromConfiguration(const dnsdist::rust::settings::BackendConfiguration& config, bool configCheck) +{ + DownstreamState::Config backendConfig; + std::shared_ptr 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(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(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(policy, ::rust::string(policy->d_name)); + } + + try { + auto data = std::string(std::istreambuf_iterator(file), std::istreambuf_iterator()); + + 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(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(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(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(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(); + 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(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(); + 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(); + 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(); + ruleParams.d_tagSettings->d_name = std::string(rule.tag_name); + ruleParams.d_tagSettings->d_value = std::string(rule.tag_value); + } + dbrgObj->setRCodeRate(checkedConversionFromStr("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(); + ruleParams.d_tagSettings->d_name = std::string(rule.tag_name); + ruleParams.d_tagSettings->d_value = std::string(rule.tag_value); + } + dbrgObj->setRCodeRatio(checkedConversionFromStr("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(); + ruleParams.d_tagSettings->d_name = std::string(rule.tag_name); + ruleParams.d_tagSettings->d_value = std::string(rule.tag_value); + } + dbrgObj->setRCodeRate(checkedConversionFromStr("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(); + ruleParams.d_tagSettings->d_name = std::string(rule.tag_name); + ruleParams.d_tagSettings->d_value = std::string(rule.tag_value); + } + dbrgObj->setRCodeRatio(checkedConversionFromStr("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(); + 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(); + 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(); + 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(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(); + 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(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 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(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(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 optionsToSkip{EDNSOptionCode::COOKIE}; + + for (const auto& option : cache.options_to_skip) { + optionsToSkip.insert(pdns::checked_stoi(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(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(std::string(policy.name), std::string(policy.function)); + registerType(policyObj, policy.name); + } + else { + ServerPolicy::ffipolicyfunc_t function; + + if (!getOptionalLuaFunction(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(std::string(policy.name), std::move(function)); + registerType(policyObj, policy.name); + } + } + else { + ServerPolicy::policyfunc_t function; + if (!getOptionalLuaFunction(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(std::string(policy.name), std::move(function), true); + registerType(policyObj, policy.name); + } + } + + for (const auto& pool : globalConfig.pools) { + std::shared_ptr poolObj = createPoolIfNotExists(std::string(pool.name)); + if (!pool.packet_cache.empty()) { + poolObj->packetCache = getRegisteredTypeByName(pool.packet_cache); + } + if (!pool.policy.empty()) { + poolObj->policy = getRegisteredTypeByName(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 newDNSSelector(std::shared_ptr&& rule, const ::rust::String& name) +{ + auto selector = std::make_shared(); + selector->d_name = std::string(name); + selector->d_rule = std::move(rule); + dnsdist::configuration::yaml::registerType(selector, name); + return selector; +} + +static std::shared_ptr newDNSActionWrapper(std::shared_ptr&& action, const ::rust::String& name) +{ + auto wrapper = std::make_shared(); + wrapper->d_name = std::string(name); + wrapper->d_action = std::move(action); + dnsdist::configuration::yaml::registerType(wrapper, name); + return wrapper; +} + +static std::shared_ptr newDNSResponseActionWrapper(std::shared_ptr&& action, const ::rust::String& name) +{ + auto wrapper = std::make_shared(); + 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& 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 +T convertLuaFunction(const ::rust::String& context, const ::rust::String& name) +{ + T function; + if (!dnsdist::configuration::yaml::getOptionalLuaFunction(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 getContinueAction(const ContinueActionConfiguration& config) +{ + auto action = dnsdist::actions::getContinueAction(config.action.action->d_action); + return newDNSActionWrapper(std::move(action), config.name); +} + +std::shared_ptr getSetProxyProtocolValuesAction(const SetProxyProtocolValuesActionConfiguration& config) +{ + std::vector> 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 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 getSpoofAction(const SpoofActionConfiguration& config) +{ + std::vector 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 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 getSpoofRawAction(const SpoofRawActionConfiguration& config) +{ + std::vector raws; + for (const auto& answer : config.answers) { + raws.emplace_back(answer); + } + std::optional 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 getClearRecordTypesResponseAction(const ClearRecordTypesResponseActionConfiguration& config) +{ + std::unordered_set 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 getLimitTTLResponseAction(const LimitTTLResponseActionConfiguration& config) +{ + std::unordered_set 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 getSetMinTTLResponseAction(const SetMinTTLResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLimitTTLResponseAction(config.min); + return newDNSResponseActionWrapper(std::move(action), config.name); +} + +std::shared_ptr getSetMaxTTLResponseAction(const SetMaxTTLResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLimitTTLResponseAction(0, config.max); + return newDNSResponseActionWrapper(std::move(action), config.name); +} + +std::shared_ptr 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 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 getQNameSelector(const QNameSelectorConfiguration& config) +{ + return newDNSSelector(dnsdist::selectors::getQNameSelector(DNSName(std::string(config.qname))), config.name); +} + +std::shared_ptr getNetmaskGroupSelector(const NetmaskGroupSelectorConfiguration& config) +{ + std::shared_ptr nmg; + if (!config.netmask_group_name.empty()) { + nmg = dnsdist::configuration::yaml::getRegisteredTypeByName(std::string(config.netmask_group_name)); + } + if (!nmg) { + nmg = std::make_shared(); + } + 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 getKeyValueStoreLookupAction(const KeyValueStoreLookupActionConfiguration& config) +{ + auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName(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(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 getKeyValueStoreRangeLookupAction(const KeyValueStoreRangeLookupActionConfiguration& config) +{ + auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName(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(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 getKeyValueStoreLookupSelector(const KeyValueStoreLookupSelectorConfiguration& config) +{ + auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName(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(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 getKeyValueStoreRangeLookupSelector(const KeyValueStoreRangeLookupSelectorConfiguration& config) +{ + auto kvs = dnsdist::configuration::yaml::getRegisteredTypeByName(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(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 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(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(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 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(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(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 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(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(); + for (const auto& tag : config.export_tags) { + actionConfig.tagsToExport->emplace(std::string(tag)); + } + } + dnsdist::actions::ProtobufAlterFunction alterFunc; + if (dnsdist::configuration::yaml::getOptionalLuaFunction(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 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(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(); + 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(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(nullptr); + dnsdist::configuration::yaml::registerType(object, config.name); + return; + } + auto object = std::shared_ptr(std::make_shared(ComboAddress(std::string(config.address)), config.timeout, config.max_queued_entries * 100, config.reconnect_wait_time, false)); + dnsdist::configuration::yaml::registerType(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(nullptr); + dnsdist::configuration::yaml::registerType(object, config.name); + return; + } + + std::unordered_map 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(std::make_shared(family, std::string(config.address), false, options)); + dnsdist::configuration::yaml::registerType(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(std::make_shared(std::string(lmdb.file_name), std::string(lmdb.database_name), lmdb.no_lock)) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(store, lmdb.name); + } +#endif /* defined(HAVE_LMDB) */ +#if defined(HAVE_CDB) + for (const auto& cdb : config.cdb) { + auto store = createObjects ? std::shared_ptr(std::make_shared(std::string(cdb.file_name), cdb.refresh_delay)) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(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(std::make_shared(key.v4_mask, key.v6_mask, key.include_port)) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(lookup, key.name); + } + for (const auto& key : config.lookup_keys.qname_keys) { + auto lookup = createObjects ? std::shared_ptr(std::make_shared(key.wire_format)) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(lookup, key.name); + } + for (const auto& key : config.lookup_keys.suffix_keys) { + auto lookup = createObjects ? std::shared_ptr(std::make_shared(key.minimum_labels, key.wire_format)) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(lookup, key.name); + } + for (const auto& key : config.lookup_keys.tag_keys) { + auto lookup = createObjects ? std::shared_ptr(std::make_shared(std::string(key.tag))) : std::shared_ptr(); + dnsdist::configuration::yaml::registerType(lookup, key.name); + } +#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */ +} + +std::shared_ptr getAndSelector(const AndSelectorConfiguration& config) +{ + std::vector> 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 getOrSelector(const OrSelectorConfiguration& config) +{ + std::vector> 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 getNotSelector(const NotSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getNotSelector(config.selector.selector->d_rule); + return newDNSSelector(std::move(selector), config.name); +} + +std::shared_ptr getByNameSelector(const ByNameSelectorConfiguration& config) +{ + return dnsdist::configuration::yaml::getRegisteredTypeByName(config.selector_name); +} + +#include "dnsdist-rust-bridge-actions-generated.cc" +#include "dnsdist-rust-bridge-selectors-generated.cc" +} +#endif /* defined(HAVE_YAML_CONFIGURATION) */ diff --git a/pdns/dnsdistdist/dnsdist-configuration-yaml.hh b/pdns/dnsdistdist/dnsdist-configuration-yaml.hh new file mode 100644 index 0000000000..467b9df99f --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-configuration-yaml.hh @@ -0,0 +1,31 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include "config.h" + +#include + +namespace dnsdist::configuration::yaml +{ +bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool configCheck); +} diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.cc b/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.cc new file mode 100644 index 0000000000..3204c13232 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.cc @@ -0,0 +1,236 @@ +// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!! +std::shared_ptr getAllowAction(const AllowActionConfiguration& config) +{ + auto action = dnsdist::actions::getAllowAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getDelayAction(const DelayActionConfiguration& config) +{ + auto action = dnsdist::actions::getDelayAction(config.msec); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getDropAction(const DropActionConfiguration& config) +{ + auto action = dnsdist::actions::getDropAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetEDNSOptionAction(const SetEDNSOptionActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetEDNSOptionAction(config.code, std::string(config.data)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getERCodeAction(const ERCodeActionConfiguration& config) +{ + auto action = dnsdist::actions::getERCodeAction(config.rcode, convertResponseConfig(config.vars)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getHTTPStatusAction(const HTTPStatusActionConfiguration& config) +{ + auto action = dnsdist::actions::getHTTPStatusAction(config.status, PacketBuffer(config.body.data(), config.body.data() + config.body.size()), std::string(config.content_type), convertResponseConfig(config.vars)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLogAction(const LogActionConfiguration& config) +{ + auto action = dnsdist::actions::getLogAction(std::string(config.file_name), config.binary, config.append, config.buffered, config.verbose_only, config.include_timestamp); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaAction(const LuaActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaAction(convertLuaFunction("LuaActionConfiguration", config.function)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaFFIAction(const LuaFFIActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaFFIAction(convertLuaFunction("LuaFFIActionConfiguration", config.function)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaFFIPerThreadAction(const LuaFFIPerThreadActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaFFIPerThreadAction(std::string(config.code)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getNegativeAndSOAAction(const NegativeAndSOAActionConfiguration& config) +{ + auto action = dnsdist::actions::getNegativeAndSOAAction(config.nxd, DNSName(std::string(config.zone)), config.ttl, DNSName(std::string(config.mname)), DNSName(std::string(config.rname)), convertSOAParams(config.soa_parameters), config.soa_in_authority, convertResponseConfig(config.vars)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getNoneAction(const NoneActionConfiguration& config) +{ + auto action = dnsdist::actions::getNoneAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getPoolAction(const PoolActionConfiguration& config) +{ + auto action = dnsdist::actions::getPoolAction(std::string(config.pool_name), config.stop_processing); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getQPSAction(const QPSActionConfiguration& config) +{ + auto action = dnsdist::actions::getQPSAction(config.limit); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getQPSPoolAction(const QPSPoolActionConfiguration& config) +{ + auto action = dnsdist::actions::getQPSPoolAction(config.limit, std::string(config.pool_name), config.stop_processing); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getRCodeAction(const RCodeActionConfiguration& config) +{ + auto action = dnsdist::actions::getRCodeAction(config.rcode, convertResponseConfig(config.vars)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetAdditionalProxyProtocolValueAction(const SetAdditionalProxyProtocolValueActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetAdditionalProxyProtocolValueAction(config.proxy_type, std::string(config.value)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetDisableECSAction(const SetDisableECSActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetDisableECSAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetDisableValidationAction(const SetDisableValidationActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetDisableValidationAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetECSAction(const SetECSActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetECSAction(std::string(config.ipv4), std::string(config.ipv6)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetECSOverrideAction(const SetECSOverrideActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetECSOverrideAction(config.override_existing); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetECSPrefixLengthAction(const SetECSPrefixLengthActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetECSPrefixLengthAction(config.ipv4, config.ipv6); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetExtendedDNSErrorAction(const SetExtendedDNSErrorActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetExtendedDNSErrorAction(config.info_code, std::string(config.extra_text)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetMacAddrAction(const SetMacAddrActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetMacAddrAction(config.code); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetMaxReturnedTTLAction(const SetMaxReturnedTTLActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetMaxReturnedTTLAction(config.max); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetNoRecurseAction(const SetNoRecurseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetNoRecurseAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetSkipCacheAction(const SetSkipCacheActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetSkipCacheAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetTagAction(const SetTagActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetTagAction(std::string(config.tag), std::string(config.value)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetTempFailureCacheTTLAction(const SetTempFailureCacheTTLActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetTempFailureCacheTTLAction(config.maxttl); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSNMPTrapAction(const SNMPTrapActionConfiguration& config) +{ + auto action = dnsdist::actions::getSNMPTrapAction(std::string(config.reason)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSpoofSVCAction(const SpoofSVCActionConfiguration& config) +{ + auto action = dnsdist::actions::getSpoofSVCAction(convertSVCRecordParameters(config.parameters), convertResponseConfig(config.vars)); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getTCAction(const TCActionConfiguration& config) +{ + auto action = dnsdist::actions::getTCAction(); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getTeeAction(const TeeActionConfiguration& config) +{ + auto action = dnsdist::actions::getTeeAction(ComboAddress(std::string(config.rca)), ComboAddress(std::string(config.lca)), config.add_ecs, config.add_proxy_protocol); + return newDNSActionWrapper(std::move(action), config.name); +} +std::shared_ptr getAllowResponseAction(const AllowResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getAllowResponseAction(); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getDelayResponseAction(const DelayResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getDelayResponseAction(config.msec); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getDropResponseAction(const DropResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getDropResponseAction(); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLogResponseAction(const LogResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLogResponseAction(std::string(config.file_name), config.append, config.buffered, config.verbose_only, config.include_timestamp); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaResponseAction(const LuaResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaResponseAction(convertLuaFunction("LuaResponseActionConfiguration", config.function)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaFFIResponseAction(const LuaFFIResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaFFIResponseAction(convertLuaFunction("LuaFFIResponseActionConfiguration", config.function)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getLuaFFIPerThreadResponseAction(const LuaFFIPerThreadResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getLuaFFIPerThreadResponseAction(std::string(config.code)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetExtendedDNSErrorResponseAction(const SetExtendedDNSErrorResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetExtendedDNSErrorResponseAction(config.info_code, std::string(config.extra_text)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetMaxReturnedTTLResponseAction(const SetMaxReturnedTTLResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetMaxReturnedTTLResponseAction(config.max); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetReducedTTLResponseAction(const SetReducedTTLResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetReducedTTLResponseAction(config.percentage); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetSkipCacheResponseAction(const SetSkipCacheResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetSkipCacheResponseAction(); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSetTagResponseAction(const SetTagResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSetTagResponseAction(std::string(config.tag), std::string(config.value)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getSNMPTrapResponseAction(const SNMPTrapResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getSNMPTrapResponseAction(std::string(config.reason)); + return newDNSResponseActionWrapper(std::move(action), config.name); +} +std::shared_ptr getTCResponseAction(const TCResponseActionConfiguration& config) +{ + auto action = dnsdist::actions::getTCResponseAction(); + return newDNSResponseActionWrapper(std::move(action), config.name); +} diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.hh b/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.hh new file mode 100644 index 0000000000..e628aad99d --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-bridge-actions-generated.hh @@ -0,0 +1,127 @@ +// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!! +struct AllowActionConfiguration; +std::shared_ptr getAllowAction(const AllowActionConfiguration& config); +struct ContinueActionConfiguration; +std::shared_ptr getContinueAction(const ContinueActionConfiguration& config); +struct DelayActionConfiguration; +std::shared_ptr getDelayAction(const DelayActionConfiguration& config); +struct DnstapLogActionConfiguration; +std::shared_ptr getDnstapLogAction(const DnstapLogActionConfiguration& config); +struct DropActionConfiguration; +std::shared_ptr getDropAction(const DropActionConfiguration& config); +struct SetEDNSOptionActionConfiguration; +std::shared_ptr getSetEDNSOptionAction(const SetEDNSOptionActionConfiguration& config); +struct ERCodeActionConfiguration; +std::shared_ptr getERCodeAction(const ERCodeActionConfiguration& config); +struct HTTPStatusActionConfiguration; +std::shared_ptr getHTTPStatusAction(const HTTPStatusActionConfiguration& config); +struct KeyValueStoreLookupActionConfiguration; +std::shared_ptr getKeyValueStoreLookupAction(const KeyValueStoreLookupActionConfiguration& config); +struct KeyValueStoreRangeLookupActionConfiguration; +std::shared_ptr getKeyValueStoreRangeLookupAction(const KeyValueStoreRangeLookupActionConfiguration& config); +struct LogActionConfiguration; +std::shared_ptr getLogAction(const LogActionConfiguration& config); +struct LuaActionConfiguration; +std::shared_ptr getLuaAction(const LuaActionConfiguration& config); +struct LuaFFIActionConfiguration; +std::shared_ptr getLuaFFIAction(const LuaFFIActionConfiguration& config); +struct LuaFFIPerThreadActionConfiguration; +std::shared_ptr getLuaFFIPerThreadAction(const LuaFFIPerThreadActionConfiguration& config); +struct NegativeAndSOAActionConfiguration; +std::shared_ptr getNegativeAndSOAAction(const NegativeAndSOAActionConfiguration& config); +struct NoneActionConfiguration; +std::shared_ptr getNoneAction(const NoneActionConfiguration& config); +struct PoolActionConfiguration; +std::shared_ptr getPoolAction(const PoolActionConfiguration& config); +struct QPSActionConfiguration; +std::shared_ptr getQPSAction(const QPSActionConfiguration& config); +struct QPSPoolActionConfiguration; +std::shared_ptr getQPSPoolAction(const QPSPoolActionConfiguration& config); +struct RCodeActionConfiguration; +std::shared_ptr getRCodeAction(const RCodeActionConfiguration& config); +struct RemoteLogActionConfiguration; +std::shared_ptr getRemoteLogAction(const RemoteLogActionConfiguration& config); +struct SetAdditionalProxyProtocolValueActionConfiguration; +std::shared_ptr getSetAdditionalProxyProtocolValueAction(const SetAdditionalProxyProtocolValueActionConfiguration& config); +struct SetDisableECSActionConfiguration; +std::shared_ptr getSetDisableECSAction(const SetDisableECSActionConfiguration& config); +struct SetDisableValidationActionConfiguration; +std::shared_ptr getSetDisableValidationAction(const SetDisableValidationActionConfiguration& config); +struct SetECSActionConfiguration; +std::shared_ptr getSetECSAction(const SetECSActionConfiguration& config); +struct SetECSOverrideActionConfiguration; +std::shared_ptr getSetECSOverrideAction(const SetECSOverrideActionConfiguration& config); +struct SetECSPrefixLengthActionConfiguration; +std::shared_ptr getSetECSPrefixLengthAction(const SetECSPrefixLengthActionConfiguration& config); +struct SetExtendedDNSErrorActionConfiguration; +std::shared_ptr getSetExtendedDNSErrorAction(const SetExtendedDNSErrorActionConfiguration& config); +struct SetMacAddrActionConfiguration; +std::shared_ptr getSetMacAddrAction(const SetMacAddrActionConfiguration& config); +struct SetMaxReturnedTTLActionConfiguration; +std::shared_ptr getSetMaxReturnedTTLAction(const SetMaxReturnedTTLActionConfiguration& config); +struct SetNoRecurseActionConfiguration; +std::shared_ptr getSetNoRecurseAction(const SetNoRecurseActionConfiguration& config); +struct SetProxyProtocolValuesActionConfiguration; +std::shared_ptr getSetProxyProtocolValuesAction(const SetProxyProtocolValuesActionConfiguration& config); +struct SetSkipCacheActionConfiguration; +std::shared_ptr getSetSkipCacheAction(const SetSkipCacheActionConfiguration& config); +struct SetTagActionConfiguration; +std::shared_ptr getSetTagAction(const SetTagActionConfiguration& config); +struct SetTempFailureCacheTTLActionConfiguration; +std::shared_ptr getSetTempFailureCacheTTLAction(const SetTempFailureCacheTTLActionConfiguration& config); +struct SNMPTrapActionConfiguration; +std::shared_ptr getSNMPTrapAction(const SNMPTrapActionConfiguration& config); +struct SpoofActionConfiguration; +std::shared_ptr getSpoofAction(const SpoofActionConfiguration& config); +struct SpoofCNAMEActionConfiguration; +std::shared_ptr getSpoofCNAMEAction(const SpoofCNAMEActionConfiguration& config); +struct SpoofPacketActionConfiguration; +std::shared_ptr getSpoofPacketAction(const SpoofPacketActionConfiguration& config); +struct SpoofRawActionConfiguration; +std::shared_ptr getSpoofRawAction(const SpoofRawActionConfiguration& config); +struct SpoofSVCActionConfiguration; +std::shared_ptr getSpoofSVCAction(const SpoofSVCActionConfiguration& config); +struct TCActionConfiguration; +std::shared_ptr getTCAction(const TCActionConfiguration& config); +struct TeeActionConfiguration; +std::shared_ptr getTeeAction(const TeeActionConfiguration& config); +struct AllowResponseActionConfiguration; +std::shared_ptr getAllowResponseAction(const AllowResponseActionConfiguration& config); +struct ClearRecordTypesResponseActionConfiguration; +std::shared_ptr getClearRecordTypesResponseAction(const ClearRecordTypesResponseActionConfiguration& config); +struct DelayResponseActionConfiguration; +std::shared_ptr getDelayResponseAction(const DelayResponseActionConfiguration& config); +struct DnstapLogResponseActionConfiguration; +std::shared_ptr getDnstapLogResponseAction(const DnstapLogResponseActionConfiguration& config); +struct DropResponseActionConfiguration; +std::shared_ptr getDropResponseAction(const DropResponseActionConfiguration& config); +struct LimitTTLResponseActionConfiguration; +std::shared_ptr getLimitTTLResponseAction(const LimitTTLResponseActionConfiguration& config); +struct LogResponseActionConfiguration; +std::shared_ptr getLogResponseAction(const LogResponseActionConfiguration& config); +struct LuaResponseActionConfiguration; +std::shared_ptr getLuaResponseAction(const LuaResponseActionConfiguration& config); +struct LuaFFIResponseActionConfiguration; +std::shared_ptr getLuaFFIResponseAction(const LuaFFIResponseActionConfiguration& config); +struct LuaFFIPerThreadResponseActionConfiguration; +std::shared_ptr getLuaFFIPerThreadResponseAction(const LuaFFIPerThreadResponseActionConfiguration& config); +struct RemoteLogResponseActionConfiguration; +std::shared_ptr getRemoteLogResponseAction(const RemoteLogResponseActionConfiguration& config); +struct SetExtendedDNSErrorResponseActionConfiguration; +std::shared_ptr getSetExtendedDNSErrorResponseAction(const SetExtendedDNSErrorResponseActionConfiguration& config); +struct SetMaxReturnedTTLResponseActionConfiguration; +std::shared_ptr getSetMaxReturnedTTLResponseAction(const SetMaxReturnedTTLResponseActionConfiguration& config); +struct SetMaxTTLResponseActionConfiguration; +std::shared_ptr getSetMaxTTLResponseAction(const SetMaxTTLResponseActionConfiguration& config); +struct SetMinTTLResponseActionConfiguration; +std::shared_ptr getSetMinTTLResponseAction(const SetMinTTLResponseActionConfiguration& config); +struct SetReducedTTLResponseActionConfiguration; +std::shared_ptr getSetReducedTTLResponseAction(const SetReducedTTLResponseActionConfiguration& config); +struct SetSkipCacheResponseActionConfiguration; +std::shared_ptr getSetSkipCacheResponseAction(const SetSkipCacheResponseActionConfiguration& config); +struct SetTagResponseActionConfiguration; +std::shared_ptr getSetTagResponseAction(const SetTagResponseActionConfiguration& config); +struct SNMPTrapResponseActionConfiguration; +std::shared_ptr getSNMPTrapResponseAction(const SNMPTrapResponseActionConfiguration& config); +struct TCResponseActionConfiguration; +std::shared_ptr getTCResponseAction(const TCResponseActionConfiguration& config); diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.cc b/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.cc new file mode 100644 index 0000000000..8ae735d51b --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.cc @@ -0,0 +1,171 @@ +// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!! +std::shared_ptr getAllSelector(const AllSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getAllSelector(); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getDNSSECSelector(const DNSSECSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getDNSSECSelector(); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getDSTPortSelector(const DSTPortSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getDSTPortSelector(config.port); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getEDNSOptionSelector(const EDNSOptionSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getEDNSOptionSelector(config.option_code); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getEDNSVersionSelector(const EDNSVersionSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getEDNSVersionSelector(config.version); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getERCodeSelector(const ERCodeSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getERCodeSelector(config.rcode); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getHTTPHeaderSelector(const HTTPHeaderSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getHTTPHeaderSelector(std::string(config.header), std::string(config.expression)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getHTTPPathSelector(const HTTPPathSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getHTTPPathSelector(std::string(config.path)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getHTTPPathRegexSelector(const HTTPPathRegexSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getHTTPPathRegexSelector(std::string(config.expression)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getLuaSelector(const LuaSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getLuaSelector(convertLuaFunction("LuaSelectorConfiguration", config.function)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getLuaFFISelector(const LuaFFISelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getLuaFFISelector(convertLuaFunction("LuaFFISelectorConfiguration", config.function)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getLuaFFIPerThreadSelector(const LuaFFIPerThreadSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getLuaFFIPerThreadSelector(std::string(config.code)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getMaxQPSSelector(const MaxQPSSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getMaxQPSSelector(config.qps, config.burst); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getMaxQPSIPSelector(const MaxQPSIPSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getMaxQPSIPSelector(config.qps, config.ipv4_mask, config.ipv6_mask, config.burst, config.expiration, config.cleanup_delay, config.scan_fraction, config.shards); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getOpcodeSelector(const OpcodeSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getOpcodeSelector(config.code); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getPayloadSizeSelector(const PayloadSizeSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getPayloadSizeSelector(std::string(config.comparison), config.size); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getPoolAvailableSelector(const PoolAvailableSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getPoolAvailableSelector(std::string(config.pool)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getPoolOutstandingSelector(const PoolOutstandingSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getPoolOutstandingSelector(std::string(config.pool), config.max_outstanding); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getProbaSelector(const ProbaSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getProbaSelector(config.probability); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getProxyProtocolValueSelector(const ProxyProtocolValueSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getProxyProtocolValueSelector(config.option_type, std::string(config.option_value)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getQClassSelector(const QClassSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getQClassSelector(std::string(config.qclass), config.numeric_value); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getQNameLabelsCountSelector(const QNameLabelsCountSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getQNameLabelsCountSelector(config.min_labels_count, config.max_labels_count); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getQNameWireLengthSelector(const QNameWireLengthSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getQNameWireLengthSelector(config.min, config.max); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getQTypeSelector(const QTypeSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getQTypeSelector(std::string(config.qtype), config.numeric_value); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRCodeSelector(const RCodeSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRCodeSelector(config.rcode); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRDSelector(const RDSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRDSelector(); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRE2Selector(const RE2SelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRE2Selector(std::string(config.expression)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRecordsCountSelector(const RecordsCountSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRecordsCountSelector(config.section, config.minimum, config.maximum); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRecordsTypeCountSelector(const RecordsTypeCountSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRecordsTypeCountSelector(config.section, config.record_type, config.minimum, config.maximum); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getRegexSelector(const RegexSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getRegexSelector(std::string(config.expression)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getSNISelector(const SNISelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getSNISelector(std::string(config.server_name)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getTagSelector(const TagSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getTagSelector(std::string(config.tag), std::string(config.value)); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getTCPSelector(const TCPSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getTCPSelector(config.tcp); + return newDNSSelector(std::move(selector), config.name); +} +std::shared_ptr getTrailingDataSelector(const TrailingDataSelectorConfiguration& config) +{ + auto selector = dnsdist::selectors::getTrailingDataSelector(); + return newDNSSelector(std::move(selector), config.name); +} diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.hh b/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.hh new file mode 100644 index 0000000000..796c3480a8 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-bridge-selectors-generated.hh @@ -0,0 +1,89 @@ +// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!! +struct AllSelectorConfiguration; +std::shared_ptr getAllSelector(const AllSelectorConfiguration& config); +struct AndSelectorConfiguration; +std::shared_ptr getAndSelector(const AndSelectorConfiguration& config); +struct ByNameSelectorConfiguration; +std::shared_ptr getByNameSelector(const ByNameSelectorConfiguration& config); +struct DNSSECSelectorConfiguration; +std::shared_ptr getDNSSECSelector(const DNSSECSelectorConfiguration& config); +struct DSTPortSelectorConfiguration; +std::shared_ptr getDSTPortSelector(const DSTPortSelectorConfiguration& config); +struct EDNSOptionSelectorConfiguration; +std::shared_ptr getEDNSOptionSelector(const EDNSOptionSelectorConfiguration& config); +struct EDNSVersionSelectorConfiguration; +std::shared_ptr getEDNSVersionSelector(const EDNSVersionSelectorConfiguration& config); +struct ERCodeSelectorConfiguration; +std::shared_ptr getERCodeSelector(const ERCodeSelectorConfiguration& config); +struct HTTPHeaderSelectorConfiguration; +std::shared_ptr getHTTPHeaderSelector(const HTTPHeaderSelectorConfiguration& config); +struct HTTPPathSelectorConfiguration; +std::shared_ptr getHTTPPathSelector(const HTTPPathSelectorConfiguration& config); +struct HTTPPathRegexSelectorConfiguration; +std::shared_ptr getHTTPPathRegexSelector(const HTTPPathRegexSelectorConfiguration& config); +struct KeyValueStoreLookupSelectorConfiguration; +std::shared_ptr getKeyValueStoreLookupSelector(const KeyValueStoreLookupSelectorConfiguration& config); +struct KeyValueStoreRangeLookupSelectorConfiguration; +std::shared_ptr getKeyValueStoreRangeLookupSelector(const KeyValueStoreRangeLookupSelectorConfiguration& config); +struct LuaSelectorConfiguration; +std::shared_ptr getLuaSelector(const LuaSelectorConfiguration& config); +struct LuaFFISelectorConfiguration; +std::shared_ptr getLuaFFISelector(const LuaFFISelectorConfiguration& config); +struct LuaFFIPerThreadSelectorConfiguration; +std::shared_ptr getLuaFFIPerThreadSelector(const LuaFFIPerThreadSelectorConfiguration& config); +struct MaxQPSSelectorConfiguration; +std::shared_ptr getMaxQPSSelector(const MaxQPSSelectorConfiguration& config); +struct MaxQPSIPSelectorConfiguration; +std::shared_ptr getMaxQPSIPSelector(const MaxQPSIPSelectorConfiguration& config); +struct NetmaskGroupSelectorConfiguration; +std::shared_ptr getNetmaskGroupSelector(const NetmaskGroupSelectorConfiguration& config); +struct NotSelectorConfiguration; +std::shared_ptr getNotSelector(const NotSelectorConfiguration& config); +struct OpcodeSelectorConfiguration; +std::shared_ptr getOpcodeSelector(const OpcodeSelectorConfiguration& config); +struct OrSelectorConfiguration; +std::shared_ptr getOrSelector(const OrSelectorConfiguration& config); +struct PayloadSizeSelectorConfiguration; +std::shared_ptr getPayloadSizeSelector(const PayloadSizeSelectorConfiguration& config); +struct PoolAvailableSelectorConfiguration; +std::shared_ptr getPoolAvailableSelector(const PoolAvailableSelectorConfiguration& config); +struct PoolOutstandingSelectorConfiguration; +std::shared_ptr getPoolOutstandingSelector(const PoolOutstandingSelectorConfiguration& config); +struct ProbaSelectorConfiguration; +std::shared_ptr getProbaSelector(const ProbaSelectorConfiguration& config); +struct ProxyProtocolValueSelectorConfiguration; +std::shared_ptr getProxyProtocolValueSelector(const ProxyProtocolValueSelectorConfiguration& config); +struct QClassSelectorConfiguration; +std::shared_ptr getQClassSelector(const QClassSelectorConfiguration& config); +struct QNameSelectorConfiguration; +std::shared_ptr getQNameSelector(const QNameSelectorConfiguration& config); +struct QNameLabelsCountSelectorConfiguration; +std::shared_ptr getQNameLabelsCountSelector(const QNameLabelsCountSelectorConfiguration& config); +struct QNameSetSelectorConfiguration; +std::shared_ptr getQNameSetSelector(const QNameSetSelectorConfiguration& config); +struct QNameSuffixSelectorConfiguration; +std::shared_ptr getQNameSuffixSelector(const QNameSuffixSelectorConfiguration& config); +struct QNameWireLengthSelectorConfiguration; +std::shared_ptr getQNameWireLengthSelector(const QNameWireLengthSelectorConfiguration& config); +struct QTypeSelectorConfiguration; +std::shared_ptr getQTypeSelector(const QTypeSelectorConfiguration& config); +struct RCodeSelectorConfiguration; +std::shared_ptr getRCodeSelector(const RCodeSelectorConfiguration& config); +struct RDSelectorConfiguration; +std::shared_ptr getRDSelector(const RDSelectorConfiguration& config); +struct RE2SelectorConfiguration; +std::shared_ptr getRE2Selector(const RE2SelectorConfiguration& config); +struct RecordsCountSelectorConfiguration; +std::shared_ptr getRecordsCountSelector(const RecordsCountSelectorConfiguration& config); +struct RecordsTypeCountSelectorConfiguration; +std::shared_ptr getRecordsTypeCountSelector(const RecordsTypeCountSelectorConfiguration& config); +struct RegexSelectorConfiguration; +std::shared_ptr getRegexSelector(const RegexSelectorConfiguration& config); +struct SNISelectorConfiguration; +std::shared_ptr getSNISelector(const SNISelectorConfiguration& config); +struct TagSelectorConfiguration; +std::shared_ptr getTagSelector(const TagSelectorConfiguration& config); +struct TCPSelectorConfiguration; +std::shared_ptr getTCPSelector(const TCPSelectorConfiguration& config); +struct TrailingDataSelectorConfiguration; +std::shared_ptr getTrailingDataSelector(const TrailingDataSelectorConfiguration& config); diff --git a/pdns/dnsdistdist/dnsdist-rust-bridge.hh b/pdns/dnsdistdist/dnsdist-rust-bridge.hh new file mode 100644 index 0000000000..8ac417839a --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-bridge.hh @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +class DNSAction; +class DNSResponseAction; +class DNSRule; + +#include "rust/cxx.h" + +namespace dnsdist::rust::settings +{ + +struct DNSSelector +{ + std::shared_ptr d_rule; + std::string d_name; +}; + +struct DNSActionWrapper +{ + std::shared_ptr d_action; + std::string d_name; +}; + +struct DNSResponseActionWrapper +{ + std::shared_ptr d_action; + std::string d_name; +}; + +struct ProtobufLoggerConfiguration; +struct DnstapLoggerConfiguration; +struct KeyValueStoresConfiguration; + +void registerProtobufLogger(const ProtobufLoggerConfiguration& config); +void registerDnstapLogger(const DnstapLoggerConfiguration& config); +void registerKVSObjects(const KeyValueStoresConfiguration& config); + +#include "dnsdist-rust-bridge-actions-generated.hh" +#include "dnsdist-rust-bridge-selectors-generated.hh" +} diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/Makefile.am b/pdns/dnsdistdist/dnsdist-rust-lib/Makefile.am index 65595f3547..ece3a11428 100644 --- a/pdns/dnsdistdist/dnsdist-rust-lib/Makefile.am +++ b/pdns/dnsdistdist/dnsdist-rust-lib/Makefile.am @@ -1,4 +1,23 @@ EXTRA_DIST = \ + dnsdist-configuration-yaml-items-generated-pre-in.cc \ + dnsdist-configuration-yaml-items-generated.cc \ + dnsdist-settings-generator.py \ + rust-pre-in.rs \ + rust-middle-in.rs \ + rust-post-in.rs \ rust/src/lib.rs -all: +BUILT_SOURCES=rust/src/lib.rs \ + dnsdist-configuration-yaml-items-generated.cc + +all: rust/src/lib.rs dnsdist-configuration-yaml-items-generated.cc + +rust/src/lib.rs dnsdist-configuration-yaml-items-generated.cc: dnsdist-settings-generator.py ../dnsdist-settings-definitions.yml rust-pre-in.rs rust-middle-in.rs rust-post-in.rs dnsdist-configuration-yaml-items-generated-pre-in.cc ../dnsdist-actions-definitions.yml ../dnsdist-response-actions-definitions.yml ../dnsdist-selectors-definitions.yml + @if test "$(PYTHON)" = ":"; then echo "Settings definitions have changed, python is needed to regenerate the related settings files but python was not found. Please install python and re-run configure"; exit 1; fi + @if ! $(PYTHON) --version | grep -q "Python 3"; then echo $(PYTHON) should be at least version 3. Please install python 3 and re-run configure; exit 1; fi + $(MAKE) -C rust clean + (cd ${srcdir} && $(PYTHON) dnsdist-settings-generator.py ../dnsdist-settings-definitions.yml) + +clean-local: + rm -f dnsdist-configuration-yaml-items-generated.cc + rm -f rust/src/lib.rs diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated-pre-in.cc b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated-pre-in.cc new file mode 100644 index 0000000000..bae85b634c --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated-pre-in.cc @@ -0,0 +1,24 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-configuration.hh" +#include "dnsdist-configuration-yaml.hh" diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated.cc b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated.cc new file mode 100644 index 0000000000..697ee5bc85 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-configuration-yaml-items-generated.cc @@ -0,0 +1,223 @@ +// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!! +// START INCLUDE ./dnsdist-configuration-yaml-items-generated-pre-in.cc +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist-configuration.hh" +#include "dnsdist-configuration-yaml.hh" +// END INCLUDE ./dnsdist-configuration-yaml-items-generated-pre-in.cc +#if defined(HAVE_YAML_CONFIGURATION) +#include "rust/cxx.h" +#include "rust/lib.rs.h" +#include "dnsdist-configuration-yaml-internal.hh" + +namespace dnsdist::configuration::yaml +{ +void convertRuntimeFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::RuntimeConfiguration& config) +{ + if (yamlConfig.console.maximum_output_size != 10000000 && config.d_consoleOutputMsgMaxSize == 10000000) { + config.d_consoleOutputMsgMaxSize = yamlConfig.console.maximum_output_size; + } + if (yamlConfig.console.log_connections != true && config.d_logConsoleConnections == true) { + config.d_logConsoleConnections = yamlConfig.console.log_connections; + } + if (yamlConfig.edns_client_subnet.override_existing != false && config.d_ecsOverride == false) { + config.d_ecsOverride = yamlConfig.edns_client_subnet.override_existing; + } + if (yamlConfig.edns_client_subnet.source_prefix_v4 != 32 && config.d_ECSSourcePrefixV4 == 32) { + config.d_ECSSourcePrefixV4 = yamlConfig.edns_client_subnet.source_prefix_v4; + } + if (yamlConfig.edns_client_subnet.source_prefix_v6 != 56 && config.d_ECSSourcePrefixV6 == 56) { + config.d_ECSSourcePrefixV6 = yamlConfig.edns_client_subnet.source_prefix_v6; + } + if (yamlConfig.dynamic_rules_settings.purge_interval != 60 && config.d_dynBlocksPurgeInterval == 60) { + config.d_dynBlocksPurgeInterval = yamlConfig.dynamic_rules_settings.purge_interval; + } + if (yamlConfig.tuning.tcp.receive_timeout != 2 && config.d_tcpRecvTimeout == 2) { + config.d_tcpRecvTimeout = yamlConfig.tuning.tcp.receive_timeout; + } + if (yamlConfig.tuning.tcp.send_timeout != 2 && config.d_tcpSendTimeout == 2) { + config.d_tcpSendTimeout = yamlConfig.tuning.tcp.send_timeout; + } + if (yamlConfig.tuning.tcp.max_queries_per_connection != 0 && config.d_maxTCPQueriesPerConn == 0) { + config.d_maxTCPQueriesPerConn = yamlConfig.tuning.tcp.max_queries_per_connection; + } + if (yamlConfig.tuning.tcp.max_connection_duration != 0 && config.d_maxTCPConnectionDuration == 0) { + config.d_maxTCPConnectionDuration = yamlConfig.tuning.tcp.max_connection_duration; + } + if (yamlConfig.tuning.tls.outgoing_tickets_cache_cleanup_delay != 60 && config.d_tlsSessionCacheCleanupDelay == 60) { + config.d_tlsSessionCacheCleanupDelay = yamlConfig.tuning.tls.outgoing_tickets_cache_cleanup_delay; + } + if (yamlConfig.tuning.tls.outgoing_tickets_cache_validity != 600 && config.d_tlsSessionCacheSessionValidity == 600) { + config.d_tlsSessionCacheSessionValidity = yamlConfig.tuning.tls.outgoing_tickets_cache_validity; + } + if (yamlConfig.tuning.tls.max_outgoing_tickets_per_backend != 20 && config.d_tlsSessionCacheMaxSessionsPerBackend == 20) { + config.d_tlsSessionCacheMaxSessionsPerBackend = yamlConfig.tuning.tls.max_outgoing_tickets_per_backend; + } + if (yamlConfig.cache_settings.stale_entries_ttl != 0 && config.d_staleCacheEntriesTTL == 0) { + config.d_staleCacheEntriesTTL = yamlConfig.cache_settings.stale_entries_ttl; + } + if (yamlConfig.cache_settings.cleaning_delay != 60 && config.d_cacheCleaningDelay == 60) { + config.d_cacheCleaningDelay = yamlConfig.cache_settings.cleaning_delay; + } + if (yamlConfig.cache_settings.cleaning_percentage != 100 && config.d_cacheCleaningPercentage == 100) { + config.d_cacheCleaningPercentage = yamlConfig.cache_settings.cleaning_percentage; + } + if (yamlConfig.security_polling.polling_interval != 3600 && config.d_secPollInterval == 3600) { + config.d_secPollInterval = yamlConfig.security_polling.polling_interval; + } + if (yamlConfig.security_polling.suffix != "secpoll.powerdns.com." && config.d_secPollSuffix == "secpoll.powerdns.com.") { + config.d_secPollSuffix = std::string(yamlConfig.security_polling.suffix); + } + if (yamlConfig.general.edns_udp_payload_size_self_generated_answers != 1232 && config.d_payloadSizeSelfGenAnswers == 1232) { + config.d_payloadSizeSelfGenAnswers = yamlConfig.general.edns_udp_payload_size_self_generated_answers; + } + if (yamlConfig.general.add_edns_to_self_generated_answers != true && config.d_addEDNSToSelfGeneratedResponses == true) { + config.d_addEDNSToSelfGeneratedResponses = yamlConfig.general.add_edns_to_self_generated_answers; + } + if (yamlConfig.general.truncate_tc_answers != false && config.d_truncateTC == false) { + config.d_truncateTC = yamlConfig.general.truncate_tc_answers; + } + if (yamlConfig.general.fixup_case != false && config.d_fixupCase == false) { + config.d_fixupCase = yamlConfig.general.fixup_case; + } + if (yamlConfig.general.verbose != false && config.d_verbose == false) { + config.d_verbose = yamlConfig.general.verbose; + } + if (yamlConfig.general.verbose_health_checks != false && config.d_verboseHealthChecks == false) { + config.d_verboseHealthChecks = yamlConfig.general.verbose_health_checks; + } + if (yamlConfig.general.allow_empty_responses != false && config.d_allowEmptyResponse == false) { + config.d_allowEmptyResponse = yamlConfig.general.allow_empty_responses; + } + if (yamlConfig.general.drop_empty_queries != false && config.d_dropEmptyQueries == false) { + config.d_dropEmptyQueries = yamlConfig.general.drop_empty_queries; + } + if (yamlConfig.proxy_protocol.maximum_payload_size != 512 && config.d_proxyProtocolMaximumSize == 512) { + config.d_proxyProtocolMaximumSize = yamlConfig.proxy_protocol.maximum_payload_size; + } + if (yamlConfig.proxy_protocol.apply_acl_to_proxied_clients != false && config.d_applyACLToProxiedClients == false) { + config.d_applyACLToProxiedClients = yamlConfig.proxy_protocol.apply_acl_to_proxied_clients; + } + if (yamlConfig.load_balancing_policies.servfail_on_no_server != false && config.d_servFailOnNoPolicy == false) { + config.d_servFailOnNoPolicy = yamlConfig.load_balancing_policies.servfail_on_no_server; + } + if (yamlConfig.load_balancing_policies.round_robin_servfail_on_no_server != false && config.d_roundrobinFailOnNoServer == false) { + config.d_roundrobinFailOnNoServer = yamlConfig.load_balancing_policies.round_robin_servfail_on_no_server; + } +} +void convertImmutableFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::ImmutableConfiguration& config) +{ + if (yamlConfig.console.max_concurrent_connections != 0 && config.d_consoleMaxConcurrentConnections == 0) { + config.d_consoleMaxConcurrentConnections = yamlConfig.console.max_concurrent_connections; + } + if (yamlConfig.ring_buffers.size != 10000 && config.d_ringsCapacity == 10000) { + config.d_ringsCapacity = yamlConfig.ring_buffers.size; + } + if (yamlConfig.ring_buffers.shards != 10 && config.d_ringsNumberOfShards == 10) { + config.d_ringsNumberOfShards = yamlConfig.ring_buffers.shards; + } + if (yamlConfig.ring_buffers.lock_retries != 5 && config.d_ringsNbLockTries == 5) { + config.d_ringsNbLockTries = yamlConfig.ring_buffers.lock_retries; + } + if (yamlConfig.ring_buffers.record_queries != true && config.d_ringsRecordQueries == true) { + config.d_ringsRecordQueries = yamlConfig.ring_buffers.record_queries; + } + if (yamlConfig.ring_buffers.record_responses != true && config.d_ringsRecordResponses == true) { + config.d_ringsRecordResponses = yamlConfig.ring_buffers.record_responses; + } + if (yamlConfig.tuning.tcp.worker_threads != 10 && config.d_maxTCPClientThreads == 10) { + config.d_maxTCPClientThreads = yamlConfig.tuning.tcp.worker_threads; + } + if (yamlConfig.tuning.tcp.max_queued_connections != 10000 && config.d_maxTCPQueuedConnections == 10000) { + config.d_maxTCPQueuedConnections = yamlConfig.tuning.tcp.max_queued_connections; + } + if (yamlConfig.tuning.tcp.internal_pipe_buffer_size != 1048576 && config.d_tcpInternalPipeBufferSize == 1048576) { + config.d_tcpInternalPipeBufferSize = yamlConfig.tuning.tcp.internal_pipe_buffer_size; + } + if (yamlConfig.tuning.tcp.outgoing_max_idle_time != 300 && config.d_outgoingTCPMaxIdleTime == 300) { + config.d_outgoingTCPMaxIdleTime = yamlConfig.tuning.tcp.outgoing_max_idle_time; + } + if (yamlConfig.tuning.tcp.outgoing_cleanup_interval != 60 && config.d_outgoingTCPCleanupInterval == 60) { + config.d_outgoingTCPCleanupInterval = yamlConfig.tuning.tcp.outgoing_cleanup_interval; + } + if (yamlConfig.tuning.tcp.outgoing_max_idle_connection_per_backend != 10 && config.d_outgoingTCPMaxIdlePerBackend == 10) { + config.d_outgoingTCPMaxIdlePerBackend = yamlConfig.tuning.tcp.outgoing_max_idle_connection_per_backend; + } + if (yamlConfig.tuning.tcp.max_connections_per_client != 0 && config.d_maxTCPConnectionsPerClient == 0) { + config.d_maxTCPConnectionsPerClient = yamlConfig.tuning.tcp.max_connections_per_client; + } + if (yamlConfig.tuning.udp.messages_per_round != 1 && config.d_udpVectorSize == 1) { + config.d_udpVectorSize = yamlConfig.tuning.udp.messages_per_round; + } + if (yamlConfig.tuning.udp.send_buffer_size != 0 && config.d_socketUDPSendBuffer == 0) { + config.d_socketUDPSendBuffer = yamlConfig.tuning.udp.send_buffer_size; + } + if (yamlConfig.tuning.udp.receive_buffer_size != 0 && config.d_socketUDPRecvBuffer == 0) { + config.d_socketUDPRecvBuffer = yamlConfig.tuning.udp.receive_buffer_size; + } + if (yamlConfig.tuning.udp.max_outstanding_per_backend != 65535 && config.d_maxUDPOutstanding == 65535) { + config.d_maxUDPOutstanding = yamlConfig.tuning.udp.max_outstanding_per_backend; + } + if (yamlConfig.tuning.udp.timeout != 2 && config.d_udpTimeout == 2) { + config.d_udpTimeout = yamlConfig.tuning.udp.timeout; + } + if (yamlConfig.tuning.udp.randomize_outgoing_sockets_to_backend != false && config.d_randomizeUDPSocketsToBackend == false) { + config.d_randomizeUDPSocketsToBackend = yamlConfig.tuning.udp.randomize_outgoing_sockets_to_backend; + } + if (yamlConfig.tuning.udp.randomize_ids_to_backend != false && config.d_randomizeIDsToBackend == false) { + config.d_randomizeIDsToBackend = yamlConfig.tuning.udp.randomize_ids_to_backend; + } + if (yamlConfig.tuning.doh.outgoing_worker_threads != 10 && config.d_outgoingDoHWorkers == 10) { + config.d_outgoingDoHWorkers = yamlConfig.tuning.doh.outgoing_worker_threads; + } + if (yamlConfig.tuning.doh.outgoing_max_idle_time != 300 && config.d_outgoingDoHMaxIdleTime == 300) { + config.d_outgoingDoHMaxIdleTime = yamlConfig.tuning.doh.outgoing_max_idle_time; + } + if (yamlConfig.tuning.doh.outgoing_cleanup_interval != 60 && config.d_outgoingDoHCleanupInterval == 60) { + config.d_outgoingDoHCleanupInterval = yamlConfig.tuning.doh.outgoing_cleanup_interval; + } + if (yamlConfig.tuning.doh.outgoing_max_idle_connection_per_backend != 10 && config.d_outgoingDoHMaxIdlePerBackend == 10) { + config.d_outgoingDoHMaxIdlePerBackend = yamlConfig.tuning.doh.outgoing_max_idle_connection_per_backend; + } + if (yamlConfig.snmp.enabled != false && config.d_snmpEnabled == false) { + config.d_snmpEnabled = yamlConfig.snmp.enabled; + } + if (yamlConfig.snmp.traps_enabled != false && config.d_snmpTrapsEnabled == false) { + config.d_snmpTrapsEnabled = yamlConfig.snmp.traps_enabled; + } + if (yamlConfig.snmp.daemon_socket != "" && config.d_snmpDaemonSocketPath == "") { + config.d_snmpDaemonSocketPath = std::string(yamlConfig.snmp.daemon_socket); + } + if (yamlConfig.load_balancing_policies.weighted_balancing_factor != 0.0 && config.d_weightedBalancingFactor == 0.0) { + config.d_weightedBalancingFactor = yamlConfig.load_balancing_policies.weighted_balancing_factor; + } + if (yamlConfig.load_balancing_policies.consistent_hashing_balancing_factor != 0.0 && config.d_consistentHashBalancingFactor == 0.0) { + config.d_consistentHashBalancingFactor = yamlConfig.load_balancing_policies.consistent_hashing_balancing_factor; + } + if (yamlConfig.load_balancing_policies.hash_perturbation != 0 && config.d_hashPerturbation == 0) { + config.d_hashPerturbation = yamlConfig.load_balancing_policies.hash_perturbation; + } +} + +} +#endif /* defined(HAVE_YAML_CONFIGURATION) */ diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-settings-generator.py b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-settings-generator.py new file mode 100644 index 0000000000..f9a7fe8a5f --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/dnsdist-settings-generator.py @@ -0,0 +1,812 @@ +#!/usr/bin/python3 +"""Load settings definitions and generates C++ and Rust code to handle them.""" +# 1/ Loads the settings definitions from +# - dnsdist-settings-definitions.yml +# and generates Rust structures and functions that are used to parse the +# YAML settings and populate the Rust structures (via Serde): +# rust/src/lib.rs +# Note that some existing structures and functions present in +# - rust-pre-in.rs +# - rust-middle-in.rs +# - rust-post-in.rs +# are also included into the final rust/src/lib.rs file +# Note that during the compilation of the Rust code to create the static +# dnsdist_rust library, the cxx module also creates corresponding C++ structures +# for interoperability +# 2/ Creates methods to fill DNSdist's internal configuration structures +# from the YAML parameters for all trivial values: +# - dnsdist-configuration-yaml-items-generated.cc +# 3/ Loads the action definitions from: +# - dnsdist-actions-definitions.yml +# - dnsdist-response-actions-definitions.yml +# and generates C++ headers and code to create the wrappers +# for these actions from the Rust structures: +# - dnsdist-rust-bridge-actions-generated.hh +# - dnsdist-rust-bridge-actions-generated.cc +# 2/ Loads the selector definitions from: +# - dnsdist-selectors-definitions.yml +# - dnsdist-rust-bridge-selectors-generated.hh +# - dnsdist-rust-bridge-selectors-generated.cc +# and generates C++ headers and code to create the wrappers +# for these selectors from the Rust structures: +# The format of the definitions, in YAML, is a simple list of items. +# Each item has a name and an optional list of parameters. +# Parameters have a name, a type, and optionally a default value +# Types are the Rust ones, converted to the C++ equivalent when needed +# Default values are written as quoted strings, with the exception of the +# special unquoted true value which means to use the default value for the +# object type, which needs to exist. +# Items can optionally have the following properties: +# - 'skip-cpp' is not used by this script but is used by the dnsdist-rules-generator.py one, where it means that the corresponding C++ factory and Lua bindinds will not be generated, which is useful for objects taking parameters that cannot be directly mapped +# - 'skip-rust' means that the C++ code to create the Rust-side version of an action or selector will not generated +# - 'skip-serde' means that the Rust structure representing that action or selector in the YAML setting will not be directly created by Serde. It is used for selectors that reference another selector themselves, or actions referencing another action. +# - 'lua-name' name of the Lua directive for this setting +# - 'internal-field-name' name of the corresponding field in DNSdist's internal configuration structures, which is used to generate 'dnsdist-configuration-yaml-items-generated.cc' +# - 'runtime-configurable' whether this setting can be set at runtime or can only be set at configuration time + +import os +import re +import sys +import tempfile +import yaml + +def quote(arg): + """Return a quoted string""" + return '"' + arg + '"' + +def get_vector_sub_type(rust_type): + return rust_type[4:-1] + +def is_vector_of(rust_type): + return rust_type.startswith('Vec<') + +def is_type_native(rust_type): + if is_vector_of(rust_type): + sub_type = get_vector_sub_type(rust_type) + return is_type_native(sub_type) + return rust_type in ['bool', 'u8', 'u16', 'u32', 'u64', 'f64', 'String'] + +def is_value_rust_default(rust_type, value): + """Is a value the same as its corresponding Rust default?""" + if rust_type == 'bool': + return value == 'false' + if rust_type in ('u8', 'u16', 'u32', 'u64'): + return value in (0, '0', '') + if rust_type == 'f64': + return value in ('0.0', 0.0) + if rust_type == 'String': + return value == '' + if rust_type == 'Vec': + # FIXME + return True + return False + +def get_rust_field_name(name): + return name.replace('-', '_').lower() + +def get_rust_object_name(name): + object_name = '' + capitalize = True + for char in name: + if char == '-': + capitalize = True + continue + if capitalize: + char = char.upper() + capitalize = False + object_name += char + + return object_name + +def gen_rust_vec_default_functions(name, type_name, def_value): + """Generate Rust code for the default handling of a vector for type_name""" + ret = f'// DEFAULT HANDLING for {name}\n' + ret += f'fn default_value_{name}() -> Vec {{\n' + ret += f' let msg = "default value defined for `{name}\' should be valid YAML";' + ret += f' let deserialized: Vec = serde_yaml::from_str({quote(def_value)}).expect(&msg);\n' + ret += ' deserialized\n' + ret += '}\n' + ret += f'fn default_value_equal_{name}(value: &Vec)' + ret += '-> bool {\n' + ret += f' let def = default_value_{name}();\n' + ret += ' &def == value\n' + ret += '}\n\n' + return ret + +# Example snippet generated +# fn default_value_general_query_local_address() -> Vec { +# vec![String::from("0.0.0.0"), ] +#} +#fn default_value_equal_general_query_local_address(value: &Vec) -> bool { +# let def = default_value_general_query_local_address(); +# &def == value +#} +def gen_rust_stringvec_default_functions(default, name): + """Generate Rust code for the default handling of a vector for Strings""" + ret = f'// DEFAULT HANDLING for {name}\n' + ret += f'fn default_value_{name}() -> Vec {{\n' + parts = re.split('[ \t,]+', default) + if len(parts) > 0: + ret += ' vec![\n' + for part in parts: + if part == '': + continue + ret += f' String::from({quote(part)}),\n' + ret += ' ]\n' + else: + ret += ' vec![]\n' + ret += '}\n' + ret += f'fn default_value_equal_{name}(value: &Vec) -> bool {{\n' + ret += f' let def = default_value_{name}();\n' + ret += ' &def == value\n' + ret += '}\n\n' + return ret + +def gen_rust_default_functions(rust_type, default, name): + """Generate Rust code for the default handling""" + if rust_type in ['Vec']: + return gen_rust_stringvec_default_functions(default, name) + ret = f'// DEFAULT HANDLING for {name}\n' + ret += f'fn default_value_{name}() -> {rust_type} {{\n' + rustdef = quote(default) + ret += f" String::from({rustdef})\n" + ret += '}\n' + if rust_type == 'String': + rust_type = 'str' + ret += f'fn default_value_equal_{name}(value: &{rust_type})' + ret += '-> bool {\n' + ret += f' value == default_value_{name}()\n' + ret += '}\n\n' + return ret + +def write_rust_default_trait_impl(struct, skip_namespace=False): + """Generate Rust code for the default Trait for a structure""" + namespace = 'dnsdistsettings::' if not skip_namespace else '' + result = '' + result += f'impl Default for {namespace}{struct} {{\n' + result += ' fn default() -> Self {\n' + result += f' let deserialized: {namespace}{struct} = serde_yaml::from_str("").unwrap();\n' + result += ' deserialized\n' + result += ' }\n' + result += '}\n\n' + return result + +def get_rust_serde_annotations(rust_type, default, rename, obj, field, default_functions): + rename_value = f'rename = "{rename}", ' if rename else '' + if default is None: + if not rename_value: + return '' + return f'#[serde({rename_value})]' + if default is True or is_value_rust_default(rust_type, default): + return f'#[serde({rename_value}default, skip_serializing_if = "crate::is_default")]' + type_upper = rust_type.capitalize() + if rust_type == 'bool': + return f'''#[serde({rename_value}default = "crate::{type_upper}::<{default}>::value", skip_serializing_if = "crate::if_true")]''' + if rust_type in ['String', 'Vec']: + basename = obj + '_' + field + default_functions.append(gen_rust_default_functions(rust_type, default, basename)) + return f'''#[serde({rename_value}default = "crate::default_value_{basename}", skip_serializing_if = "crate::default_value_equal_{basename}")]''' + return f'''#[serde({rename_value}default = "crate::{type_upper}::<{default}>::value", skip_serializing_if = "crate::{type_upper}::<{default}>::is_equal")]''' + +def get_converted_serde_type(rust_type): + if is_type_native(rust_type): + return rust_type + + if is_vector_of(rust_type): + sub_type = get_vector_sub_type(rust_type) + if sub_type in ['Action', 'Selector']: + return rust_type + if sub_type in ['QueryRuleConfiguration', 'ResponseRuleConfiguration']: + return f'Vec<{sub_type}Serde>' + return f'Vec' + + return f'dnsdistsettings::{rust_type}' + +def get_rust_struct_fields_from_definition(name, keys, default_functions, indent_spaces, special_serde_object=False): + if not 'parameters' in keys: + return '' + output = '' + indent = ' '*indent_spaces + for parameter in keys['parameters']: + parameter_name = get_rust_field_name(parameter['name']) if not 'rename' in parameter else parameter['rename'] + rust_type = parameter['type'] + if 'rust-type' in parameter: + rust_type = parameter['rust-type'] + if special_serde_object: + rust_type = get_converted_serde_type(rust_type) + else: + # cxx does not support Enums, so we have to convert them to opaque types + if rust_type == 'Action': + rust_type = 'SharedDNSAction' + elif rust_type == 'ResponseAction': + rust_type = 'SharedDNSResponseAction' + elif rust_type == 'Selector': + rust_type = 'SharedDNSSelector' + elif rust_type == 'Vec': + rust_type = 'Vec' + rename = parameter['name'] if parameter_name != parameter['name'] else None + if special_serde_object or not 'skip-serde' in keys or not keys['skip-serde']: + default_str = get_rust_serde_annotations(rust_type, parameter['default'] if 'default' in parameter else None, rename, get_rust_field_name(name), parameter_name, default_functions) + if default_str: + output += indent + default_str + '\n' + output += f'{indent}{parameter_name}: {rust_type},\n' + + return output + +def get_rust_struct_from_definition(name, keys, default_functions, indent_spaces=4, special_serde_object=False): + if not 'parameters' in keys: + return '' + obj_name = get_rust_object_name(name) + indent = ' '*indent_spaces + output = '' + if special_serde_object or not 'skip-serde' in keys or not keys['skip-serde']: + output += f'''{indent}#[derive(Deserialize, Serialize, Debug, PartialEq)] +{indent}#[serde(deny_unknown_fields)] +''' + elif name == 'global': + output += f'{indent}#[derive(Default)]\n' + + name_suffix = 'Serde' if name == 'global' and special_serde_object else '' + output += f'''{indent}struct {obj_name}Configuration{name_suffix} {{ +''' + indent_spaces += 4 + indent = ' '*indent_spaces + output += get_rust_struct_fields_from_definition(name, keys, default_functions, indent_spaces, special_serde_object=special_serde_object) + output += ' }\n' + if special_serde_object or not 'skip-serde' in keys or not keys['skip-serde']: + default_functions.append(write_rust_default_trait_impl(f'{obj_name}Configuration{name_suffix}', special_serde_object)) + return output + +def should_validate_type(rust_type): + if is_vector_of(rust_type): + sub_type = get_vector_sub_type(rust_type) + return should_validate_type(sub_type) + if rust_type in ['bool', 'u8', 'u16', 'u32', 'u64', 'f64', 'String']: + return False + if rust_type in ['Action', 'Selector', 'dnsdistsettings::SelectorsConfiguration']: + return False + return True + +def get_validation_for_field(field_name, rust_type): + if not should_validate_type(rust_type): + return '' + if not is_vector_of(rust_type): + return f' self.{field_name}.validate()?;\n' + + return f''' for sub_type in &self.{field_name} {{ + sub_type.validate()?; + }} +''' + +def get_struct_validation_function_from_definition(name, parameters, special_serde_object=False): + if len(parameters) == 0: + return '' + namespace = 'dnsdistsettings::' if not special_serde_object else '' + suffix = 'Serde' if special_serde_object else '' + struct_name = get_rust_object_name(name) + output = f'''impl {namespace}{struct_name}Configuration{suffix} {{ + fn validate(&self) -> Result<(), ValidationError> {{ +''' + for parameter in parameters: + field_name = get_rust_field_name(parameter['name']) if parameter['name'] != 'namespace' else 'name_space' + rust_type = parameter['type'] + output += get_validation_for_field(field_name, rust_type) + output += ''' Ok(()) + } +}''' + return output + +def get_definitions_from_file(def_file): + with open(def_file, 'rt', encoding="utf-8") as fd: + definitions = yaml.safe_load(fd.read()) + return definitions + +def include_file(out_fp, include_file_name): + with open(include_file_name, mode='r', encoding='utf-8') as in_fp: + out_fp.write(f'// START INCLUDE {include_file_name}\n') + out_fp.write(in_fp.read()) + out_fp.write(f'// END INCLUDE {include_file_name}\n') + +def generate_flat_settings_for_cxx(definitions, out_file_path): + cxx_flat_settings_fp = get_temporary_file_for_generated_code(out_file_path) + + include_file(cxx_flat_settings_fp, out_file_path + 'dnsdist-configuration-yaml-items-generated-pre-in.cc') + + # first we do runtime-settable settings + cxx_flat_settings_fp.write('''#if defined(HAVE_YAML_CONFIGURATION) +#include "rust/cxx.h" +#include "rust/lib.rs.h" +#include "dnsdist-configuration-yaml-internal.hh" + +namespace dnsdist::configuration::yaml +{ +void convertRuntimeFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::RuntimeConfiguration& config) +{\n''') + for category_name, keys in definitions.items(): + if not 'parameters' in keys: + continue + + if 'category' in keys: + category_name = keys['category'] + else: + category_name = get_rust_field_name(category_name) + + for parameter in keys['parameters']: + if not 'internal-field-name' in parameter or not 'runtime-configurable' in parameter or not parameter['runtime-configurable']: + continue + internal_field_name = parameter['internal-field-name'] + rust_field_name = get_rust_field_name(parameter['name']) if not 'rename' in parameter else parameter['rename'] + default = parameter['default'] if parameter['type'] != 'String' else '"' + parameter['default'] + '"' + cxx_flat_settings_fp.write(f' if (yamlConfig.{category_name}.{rust_field_name} != {default} && config.{internal_field_name} == {default}) {{\n') + if parameter['type'] != 'String': + cxx_flat_settings_fp.write(f' config.{internal_field_name} = yamlConfig.{category_name}.{rust_field_name};\n') + else: + cxx_flat_settings_fp.write(f' config.{internal_field_name} = std::string(yamlConfig.{category_name}.{rust_field_name});\n') + cxx_flat_settings_fp.write(' }\n') + + cxx_flat_settings_fp.write('''}\n''') + + # then immutable ones + cxx_flat_settings_fp.write('''void convertImmutableFlatSettingsFromRust(const dnsdist::rust::settings::GlobalConfiguration& yamlConfig, dnsdist::configuration::ImmutableConfiguration& config) +{\n''') + for category_name, keys in definitions.items(): + if not 'parameters' in keys: + continue + + if 'category' in keys: + category_name = keys['category'] + else: + category_name = get_rust_field_name(category_name) + + for parameter in keys['parameters']: + if not 'internal-field-name' in parameter or not 'runtime-configurable' in parameter or parameter['runtime-configurable']: + continue + internal_field_name = parameter['internal-field-name'] + rust_field_name = get_rust_field_name(parameter['name']) if not 'rename' in parameter else parameter['rename'] + default = parameter['default'] if parameter['type'] != 'String' else '"' + parameter['default'] + '"' + cxx_flat_settings_fp.write(f' if (yamlConfig.{category_name}.{rust_field_name} != {default} && config.{internal_field_name} == {default}) {{\n') + if parameter['type'] != 'String': + cxx_flat_settings_fp.write(f' config.{internal_field_name} = yamlConfig.{category_name}.{rust_field_name};\n') + else: + cxx_flat_settings_fp.write(f' config.{internal_field_name} = std::string(yamlConfig.{category_name}.{rust_field_name});\n') + cxx_flat_settings_fp.write(' }\n') + + cxx_flat_settings_fp.write('''}\n +} +#endif /* defined(HAVE_YAML_CONFIGURATION) */ +''') + + os.rename(cxx_flat_settings_fp.name, out_file_path + 'dnsdist-configuration-yaml-items-generated.cc') + +def generate_actions_config(output, response, default_functions): + suffix = 'ResponseAction' if response else 'Action' + actions_definitions = get_actions_definitions(response) + action_buffer = '' + for action in actions_definitions: + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + indent = ' ' * 4 + if not 'skip-serde' in action or not action['skip-serde']: + action_buffer += f'''{indent}#[derive(Deserialize, Serialize, Debug, PartialEq)] +{indent}#[serde(deny_unknown_fields)]\n''' + else: + action_buffer += f'{indent}#[derive(Default)]\n' + + action_buffer += f'{indent}struct {struct_name} {{\n' + + indent = ' ' * 8 + if not 'skip-serde' in action or not action['skip-serde']: + action_buffer += f'{indent}#[serde(default, skip_serializing_if = "crate::is_default")]\n' + action_buffer += f'{indent}name: String,\n' + + action_buffer += get_rust_struct_fields_from_definition(struct_name, action, default_functions, 8) + + action_buffer += ' }\n\n' + + output.write(action_buffer) + +def generate_selectors_config(output, default_functions): + suffix = 'Selector' + selectors_definitions = get_selectors_definitions() + selector_buffer = '' + for selector in selectors_definitions: + name = get_rust_object_name(selector['name']) + struct_name = f'{name}{suffix}Configuration' + indent = ' ' * 4 + if not 'skip-serde' in selector or not selector['skip-serde']: + selector_buffer += f'''{indent}#[derive(Deserialize, Serialize, Debug, PartialEq)] +{indent}#[serde(deny_unknown_fields)]\n''' + else: + selector_buffer += f'{indent}#[derive(Default)]\n' + + selector_buffer += f'{indent}struct {struct_name} {{\n' + + indent = ' ' * 8 + if not 'skip-serde' in selector or not selector['skip-serde']: + selector_buffer += f'{indent}#[serde(default, skip_serializing_if = "crate::is_default")]\n' + selector_buffer += f'{indent}name: String,\n' + + selector_buffer += get_rust_struct_fields_from_definition(struct_name, selector, default_functions, 8) + + selector_buffer += ' }\n\n' + + output.write(selector_buffer) + +def generate_cpp_action_headers(): + cpp_action_headers_fp = get_temporary_file_for_generated_code('..') + header_buffer = '' + + # query actions + actions_definitions = get_actions_definitions(False) + suffix = 'Action' + for action in actions_definitions: + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + header_buffer += f'struct {struct_name};\n' + header_buffer += f'std::shared_ptr get{name}{suffix}(const {struct_name}& config);\n' + + # response actions + actions_definitions = get_actions_definitions(True) + suffix = 'ResponseAction' + for action in actions_definitions: + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + header_buffer += f'struct {struct_name};\n' + header_buffer += f'std::shared_ptr get{name}{suffix}(const {struct_name}& config);\n' + + cpp_action_headers_fp.write(header_buffer) + os.rename(cpp_action_headers_fp.name, '../dnsdist-rust-bridge-actions-generated.hh') + +def generate_cpp_selector_headers(): + cpp_selector_headers_fp = get_temporary_file_for_generated_code('..') + header_buffer = '' + + selectors_definitions = get_selectors_definitions() + suffix = 'Selector' + for selector in selectors_definitions: + name = get_rust_object_name(selector['name']) + struct_name = f'{name}{suffix}Configuration' + header_buffer += f'struct {struct_name};\n' + header_buffer += f'std::shared_ptr get{name}{suffix}(const {struct_name}& config);\n' + cpp_selector_headers_fp.write(header_buffer) + os.rename(cpp_selector_headers_fp.name, '../dnsdist-rust-bridge-selectors-generated.hh') + +def get_cpp_parameters(struct_type, struct_name, parameters, skip_name): + output = '' + for parameter in parameters: + name = parameter['name'] + ptype = parameter['type'] + if name == 'name' and skip_name: + continue + pname = get_rust_field_name(name) + if len(output) > 0: + output += ', ' + field = f'{struct_name}.{pname}' + if ptype == 'PacketBuffer': + field = f'PacketBuffer({field}.data(), {field}.data() + {field}.size())' + elif ptype == 'DNSName': + field = f'DNSName(std::string({field}))' + elif ptype == 'ComboAddress': + field = f'ComboAddress(std::string({field}))' + elif ptype == 'String': + field = f'std::string({field})' + elif ptype == 'ResponseConfig': + field = f'convertResponseConfig({field})' + elif ptype == 'Vec': + field = f'convertSVCRecordParameters({field})' + elif ptype == 'SOAParams': + field = f'convertSOAParams({field})' + elif ptype in ['dnsdist::actions::LuaActionFunction', 'dnsdist::actions::LuaActionFFIFunction', 'dnsdist::actions::LuaResponseActionFunction', 'dnsdist::actions::LuaResponseActionFFIFunction', 'dnsdist::selectors::LuaSelectorFunction', 'dnsdist::selectors::LuaSelectorFFIFunction']: + field = f'convertLuaFunction<{ptype}>("{struct_type}", {field})' + output += field + return output + +def generate_cpp_action_wrappers(): + cpp_action_wrappers_fp = get_temporary_file_for_generated_code('..') + wrappers_buffer = '' + + # query actions + actions_definitions = get_actions_definitions(False) + suffix = 'Action' + for action in actions_definitions: + if 'skip-rust' in action and action['skip-rust']: + continue + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + parameters = get_cpp_parameters(struct_name, 'config', action['parameters'], True) if 'parameters' in action else '' + wrappers_buffer += f'''std::shared_ptr get{name}{suffix}(const {struct_name}& config) +{{ + auto action = dnsdist::actions::get{name}{suffix}({parameters}); + return newDNSActionWrapper(std::move(action), config.name); +}} +''' + + # response actions + actions_definitions = get_actions_definitions(True) + suffix = 'ResponseAction' + for action in actions_definitions: + if 'skip-rust' in action and action['skip-rust']: + continue + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + parameters = get_cpp_parameters(struct_name, 'config', action['parameters'], True) if 'parameters' in action else '' + wrappers_buffer += f'''std::shared_ptr get{name}{suffix}(const {struct_name}& config) +{{ + auto action = dnsdist::actions::get{name}{suffix}({parameters}); + return newDNSResponseActionWrapper(std::move(action), config.name); +}} +''' + + cpp_action_wrappers_fp.write(wrappers_buffer) + os.rename(cpp_action_wrappers_fp.name, '../dnsdist-rust-bridge-actions-generated.cc') + +def generate_cpp_selector_wrappers(): + cpp_selector_wrappers_fp = get_temporary_file_for_generated_code('..') + wrappers_buffer = '' + + selectors_definitions = get_selectors_definitions() + suffix = 'Selector' + for selector in selectors_definitions: + if 'skip-rust' in selector and selector['skip-rust']: + continue + name = get_rust_object_name(selector['name']) + struct_name = f'{name}{suffix}Configuration' + parameters = get_cpp_parameters(struct_name, 'config', selector['parameters'], True) if 'parameters' in selector else '' + wrappers_buffer += f'''std::shared_ptr get{name}{suffix}(const {struct_name}& config) +{{ + auto selector = dnsdist::selectors::get{name}{suffix}({parameters}); + return newDNSSelector(std::move(selector), config.name); +}} +''' + + cpp_selector_wrappers_fp.write(wrappers_buffer) + os.rename(cpp_selector_wrappers_fp.name, '../dnsdist-rust-bridge-selectors-generated.cc') + +def generate_rust_actions_enum(output, response): + suffix = 'ResponseAction' if response else 'Action' + actions_definitions = get_actions_definitions(response) + enum_buffer = f'''#[derive(Default, Serialize, Deserialize, Debug, PartialEq)] +#[serde(tag = "type")] +enum {suffix} {{ + #[default] + Default, +''' + + for action in actions_definitions: + name = get_rust_object_name(action['name']) + struct_name = f'{name}{suffix}Configuration' + if struct_name in ['ContinueActionConfiguration']: + # special version for Serde + enum_buffer += f' {name}({struct_name}Serde),\n' + else: + enum_buffer += f' {name}(dnsdistsettings::{struct_name}),\n' + + enum_buffer += '}\n\n' + + output.write(enum_buffer) + +def generate_rust_selectors_enum(output): + suffix = 'Selector' + selectors_definitions = get_selectors_definitions() + enum_buffer = f'''#[derive(Default, Serialize, Deserialize, Debug, PartialEq)] +#[serde(tag = "type")] +enum {suffix} {{ + #[default] + Default, +''' + + for selector in selectors_definitions: + name = get_rust_object_name(selector['name']) + struct_name = f'{name}{suffix}Configuration' + if struct_name in ['AndSelectorConfiguration', 'OrSelectorConfiguration', 'NotSelectorConfiguration']: + # special version for Serde + enum_buffer += f' {name}({struct_name}Serde),\n' + else: + enum_buffer += f' {name}(dnsdistsettings::{struct_name}),\n' + + enum_buffer += '}\n\n' + + output.write(enum_buffer) + +def get_actions_definitions(response): + def_file = '../dnsdist-response-actions-definitions.yml' if response else '../dnsdist-actions-definitions.yml' + return get_definitions_from_file(def_file) + +def get_selectors_definitions(): + def_file = '../dnsdist-selectors-definitions.yml' + return get_definitions_from_file(def_file) + +def generate_cpp_action_selector_functions_callable_from_rust(output): + output_buffer = ''' + /* + * Functions callable from Rust (actions and selectors) + */ + unsafe extern "C++" { +''' + # first query actions + actions_definitions = get_actions_definitions(False) + suffix = 'Action' + for action in actions_definitions: + name = get_rust_object_name(action['name']) + output_buffer += f' fn get{name}{suffix}(config: &{name}{suffix}Configuration) -> SharedPtr;\n' + + # then response actions + actions_definitions = get_actions_definitions(True) + suffix = 'ResponseAction' + for action in actions_definitions: + name = get_rust_object_name(action['name']) + output_buffer += f' fn get{name}{suffix}(config: &{name}{suffix}Configuration) -> SharedPtr;\n' + + # then selectors + selectors_definitions = get_selectors_definitions() + suffix = 'Selector' + for selector in selectors_definitions: + name = get_rust_object_name(selector['name']) + output_buffer += f' fn get{name}{suffix}(config: &{name}{suffix}Configuration) -> SharedPtr;\n' + + output_buffer += ' }\n' + output.write(output_buffer) + +def generate_rust_action_to_config(output, response): + suffix = 'ResponseAction' if response else 'Action' + actions_definitions = get_actions_definitions(response) + function_name = 'get_one_action_from_serde' if not response else 'get_one_response_action_from_serde' + enum_buffer = f'''fn {function_name}(action: &{suffix}) -> Option {{ + match action {{ + {suffix}::Default => {{}} +''' + + for action in actions_definitions: + name = get_rust_object_name(action['name']) + var = name.lower() + if name in ['Continue']: + enum_buffer += f''' {suffix}::{name}(cont) => {{ + let mut config: dnsdistsettings::{name}{suffix}Configuration = 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::SharedDNS{suffix} {{ + action: dnsdistsettings::get{name}{suffix}(&config), + }}); + }} +''' + else: + enum_buffer += f''' {suffix}::{name}(config) => {{ + let tmp_action = dnsdistsettings::get{name}{suffix}(&config); + return Some(dnsdistsettings::SharedDNS{suffix} {{ + action: tmp_action, + }}); + }} +''' + + enum_buffer += ''' } + None +} +''' + + output.write(enum_buffer) + +def generate_rust_selector_to_config(output): + suffix = 'Selector' + selectors_definitions = get_selectors_definitions() + function_name = 'get_one_selector_from_serde' + enum_buffer = f'''fn {function_name}(selector: &{suffix}) -> Option {{ + match selector {{ + {suffix}::Default => {{}} +''' + + for selector in selectors_definitions: + name = get_rust_object_name(selector['name']) + var = name.lower() + if name in ['And', 'Or']: + enum_buffer += f''' {suffix}::{name}({var}) => {{ + let mut config: dnsdistsettings::{name}{suffix}Configuration = Default::default(); + for sub_selector in &{var}.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::SharedDNS{suffix} {{ + selector: dnsdistsettings::get{name}{suffix}(&config), + }}); + }} +''' + elif name in ['Not']: + enum_buffer += f''' {suffix}::{name}({var}) => {{ + let mut config: dnsdistsettings::{name}{suffix}Configuration = Default::default(); + let new_selector = get_one_selector_from_serde(&*{var}.selector); + if new_selector.is_some() {{ + config.selector = new_selector.unwrap(); + }} + return Some(dnsdistsettings::SharedDNS{suffix} {{ + selector: dnsdistsettings::get{name}{suffix}(&config), + }}); + }} +''' + else: + enum_buffer += f''' {suffix}::{name}({var}) => {{ + let tmp_selector = dnsdistsettings::get{name}{suffix}(&{var}); + return Some(dnsdistsettings::SharedDNS{suffix} {{ + selector: tmp_selector, + }}); + }} +''' + + enum_buffer += ''' } + None +} +''' + + output.write(enum_buffer) + +def handle_structures(generated_fp, definitions, default_functions, validation_functions): + for definition_name, keys in definitions.items(): + generated_fp.write(get_rust_struct_from_definition(definition_name, keys, default_functions) + '\n') + validation_functions.append(get_struct_validation_function_from_definition(definition_name, keys['parameters'] if 'parameters' in keys else [])) + +def get_temporary_file_for_generated_code(directory): + generated_fp = tempfile.NamedTemporaryFile(mode='w+t', encoding='utf-8', dir=directory, delete=False) + generated_fp.write('// !! This file has been generated by dnsdist-settings-generator.py, do not edit by hand!!\n') + return generated_fp + +def main(): + if len(sys.argv) != 2: + print(f'Usage: {sys.argv[0]} ') + sys.exit(1) + + src_dir = './' + definitions = get_definitions_from_file(sys.argv[1]) + default_functions = [] + validation_functions = [] + global_objects = {} + + generate_cpp_action_headers() + generate_cpp_action_wrappers() + generate_cpp_selector_headers() + generate_cpp_selector_wrappers() + + generated_fp = get_temporary_file_for_generated_code(src_dir + '/rust/src/') + include_file(generated_fp, src_dir + 'rust-pre-in.rs') + + generate_actions_config(generated_fp, False, default_functions) + generate_actions_config(generated_fp, True, default_functions) + generate_selectors_config(generated_fp, default_functions) + + generate_flat_settings_for_cxx(definitions, src_dir) + + handle_structures(generated_fp, definitions, default_functions, validation_functions) + + generate_cpp_action_selector_functions_callable_from_rust(generated_fp) + + include_file(generated_fp, src_dir + 'rust-middle-in.rs') + # we are now outside of the dnsdistsettings namespace + + # generate the special global configuration Serde structure + for definition_name, keys in definitions.items(): + if definition_name == 'global': + generated_fp.write(get_rust_struct_from_definition(definition_name, keys, default_functions, special_serde_object=True) + '\n') + validation_functions.append(get_struct_validation_function_from_definition(definition_name, keys['parameters'] if 'parameters' in keys else [], True)) + + generate_rust_actions_enum(generated_fp, False) + generate_rust_actions_enum(generated_fp, True) + generate_rust_selectors_enum(generated_fp) + + # the generated functions for the default values and validation + for function_def in default_functions: + generated_fp.write(function_def + '\n') + + for function_def in validation_functions: + generated_fp.write(function_def + '\n') + + generate_rust_action_to_config(generated_fp, False) + generate_rust_action_to_config(generated_fp, True) + generate_rust_selector_to_config(generated_fp) + + include_file(generated_fp, src_dir + 'rust-post-in.rs') + + os.rename(generated_fp.name, src_dir + '/rust/src/lib.rs') + +if __name__ == '__main__': + main() diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs new file mode 100644 index 0000000000..6ed97c3fe1 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust-middle-in.rs @@ -0,0 +1,127 @@ + /* + * Functions callable from C++ + */ + extern "Rust" { + fn from_yaml_string(str: &str) -> Result; + } + /* + * 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, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct OrSelectorConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + selectors: Vec, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct NotSelectorConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + selector: Box, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct ContinueActionConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + action: Box, +} + +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(()) + } +} diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs new file mode 100644 index 0000000000..1209fe8bb7 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust-post-in.rs @@ -0,0 +1,124 @@ +fn get_selectors_from_serde( + selectors_from_serde: &Vec, +) -> Vec { + let mut results: Vec = 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, +) -> Vec { + let mut results: Vec = 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, +) -> Vec { + let mut results: Vec = 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 { + let serde_config: Result = + 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); +} diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust-pre-in.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust-pre-in.rs new file mode 100644 index 0000000000..7860963c48 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust-pre-in.rs @@ -0,0 +1,82 @@ +use serde::{Deserialize, Serialize}; + +mod helpers; +use helpers::*; + +// Suppresses "Deserialize unused" warning +#[derive(Deserialize, Serialize)] +struct UnusedStruct {} + +#[derive(Debug)] +pub struct ValidationError { + msg: String, +} + +#[cxx::bridge(namespace = dnsdist::rust::settings)] +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, + #[serde(default, skip_serializing_if = "crate::is_default")] + alpns: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + ipv4_hints: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + ipv6_hints: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + additional_params: Vec, + #[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, + } + + struct SharedDNSAction { + action: SharedPtr, + } + + struct SharedDNSResponseAction { + action: SharedPtr, + } diff --git a/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs b/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs index 5d614f0c44..c48b935ab4 100644 --- a/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs +++ b/pdns/dnsdistdist/dnsdist-rust-lib/rust/src/lib.rs @@ -1,3 +1,5 @@ +// !! 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; @@ -13,16 +15,4288 @@ pub struct ValidationError { } #[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, + #[serde(default, skip_serializing_if = "crate::is_default")] + alpns: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + ipv4_hints: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + ipv6_hints: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + additional_params: Vec, + #[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, + } + struct SharedDNSAction { + action: SharedPtr, + } + + struct SharedDNSResponseAction { + action: SharedPtr, + } +// 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::::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::::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::::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::::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, + #[serde(default, skip_serializing_if = "crate::is_default")] + metas: Vec, + } + + #[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, + } + + #[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, + #[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, + #[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, + #[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, + } + + #[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, + } + + #[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::::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, + #[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, + } + + #[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, + } + + #[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, + #[serde(default = "crate::Bool::::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, + } + + #[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, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + #[serde(deny_unknown_fields)] + struct QNameSuffixSelectorConfiguration { + #[serde(default, skip_serializing_if = "crate::is_default")] + name: String, + suffixes: Vec, + #[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, + backends: Vec, + binds: Vec, + cache_hit_response_rules: Vec, + cache_inserted_response_rules: Vec, + cache_miss_rules: Vec, + cache_settings: CacheSettingsConfiguration, + console: ConsoleConfiguration, + dynamic_rules: Vec, + dynamic_rules_settings: DynamicRulesSettingsConfiguration, + edns_client_subnet: EdnsClientSubnetConfiguration, + general: GeneralConfiguration, + key_value_stores: KeyValueStoresConfiguration, + load_balancing_policies: LoadBalancingPoliciesConfiguration, + metrics: MetricsConfiguration, + packet_caches: Vec, + pools: Vec, + proxy_protocol: ProxyProtocolConfiguration, + query_count: QueryCountConfiguration, + query_rules: Vec, + remote_logging: RemoteLoggingConfiguration, + response_rules: Vec, + ring_buffers: RingBuffersConfiguration, + security_polling: SecurityPollingConfiguration, + selectors: Vec, + self_answered_response_rules: Vec, + snmp: SnmpConfiguration, + tuning: TuningConfiguration, + webserver: WebserverConfiguration, + xfr_response_rules: Vec, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + #[serde(deny_unknown_fields)] + struct MetricsConfiguration { + #[serde(default, skip_serializing_if = "crate::is_default")] + carbon: Vec, + } + + #[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, + #[serde(rename = "dnstap-loggers", default, skip_serializing_if = "crate::is_default")] + dnstap_loggers: Vec, + } + + #[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::::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::::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, + #[serde(rename = "qname-keys", default, skip_serializing_if = "crate::is_default")] + qname_keys: Vec, + #[serde(rename = "suffix-keys", default, skip_serializing_if = "crate::is_default")] + suffix_keys: Vec, + #[serde(rename = "tag-keys", default, skip_serializing_if = "crate::is_default")] + tag_keys: Vec, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + #[serde(deny_unknown_fields)] + struct KeyValueStoresConfiguration { + #[serde(default, skip_serializing_if = "crate::is_default")] + lmdb: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + cdb: Vec, + #[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, + #[serde(rename = "api-requires-authentication", default = "crate::Bool::::value", skip_serializing_if = "crate::if_true")] + api_requires_authentication: bool, + #[serde(rename = "stats-require-authentication", default = "crate::Bool::::value", skip_serializing_if = "crate::if_true")] + stats_require_authentication: bool, + #[serde(rename = "dashboard-requires-authentication", default = "crate::Bool::::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, + #[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, + #[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::::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, + #[serde(rename = "include-ranges", default, skip_serializing_if = "crate::is_default")] + include_ranges: Vec, + #[serde(rename = "exclude-domains", default, skip_serializing_if = "crate::is_default")] + exclude_domains: Vec, + rules: Vec, + } + + #[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::::value", skip_serializing_if = "crate::if_true")] + record_queries: bool, + #[serde(rename = "record-responses", default = "crate::Bool::::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, + #[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::::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::::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, + #[serde(rename = "key-log-file", default, skip_serializing_if = "crate::is_default")] + key_log_file: String, + #[serde(rename = "release-buffers", default = "crate::Bool::::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::::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::::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::::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, + } + + #[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, + #[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::::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::::value", skip_serializing_if = "crate::if_true")] + early_acl_drop: bool, + #[serde(rename = "exact-path-matching", default = "crate::Bool::::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, + #[serde(rename = "responses-map", default, skip_serializing_if = "crate::is_default")] + responses_map: Vec, + } + + #[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, + } + + #[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, + #[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::::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, + #[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::::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, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + #[serde(deny_unknown_fields)] + struct PacketCacheConfiguration { + name: String, + size: u64, + #[serde(rename = "deferrable-insert-lock", default = "crate::Bool::::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, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + #[serde(deny_unknown_fields)] + struct ProxyProtocolConfiguration { + #[serde(default, skip_serializing_if = "crate::is_default")] + acl: Vec, + #[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, + #[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; + fn getContinueAction(config: &ContinueActionConfiguration) -> SharedPtr; + fn getDelayAction(config: &DelayActionConfiguration) -> SharedPtr; + fn getDnstapLogAction(config: &DnstapLogActionConfiguration) -> SharedPtr; + fn getDropAction(config: &DropActionConfiguration) -> SharedPtr; + fn getSetEDNSOptionAction(config: &SetEDNSOptionActionConfiguration) -> SharedPtr; + fn getERCodeAction(config: &ERCodeActionConfiguration) -> SharedPtr; + fn getHTTPStatusAction(config: &HTTPStatusActionConfiguration) -> SharedPtr; + fn getKeyValueStoreLookupAction(config: &KeyValueStoreLookupActionConfiguration) -> SharedPtr; + fn getKeyValueStoreRangeLookupAction(config: &KeyValueStoreRangeLookupActionConfiguration) -> SharedPtr; + fn getLogAction(config: &LogActionConfiguration) -> SharedPtr; + fn getLuaAction(config: &LuaActionConfiguration) -> SharedPtr; + fn getLuaFFIAction(config: &LuaFFIActionConfiguration) -> SharedPtr; + fn getLuaFFIPerThreadAction(config: &LuaFFIPerThreadActionConfiguration) -> SharedPtr; + fn getNegativeAndSOAAction(config: &NegativeAndSOAActionConfiguration) -> SharedPtr; + fn getNoneAction(config: &NoneActionConfiguration) -> SharedPtr; + fn getPoolAction(config: &PoolActionConfiguration) -> SharedPtr; + fn getQPSAction(config: &QPSActionConfiguration) -> SharedPtr; + fn getQPSPoolAction(config: &QPSPoolActionConfiguration) -> SharedPtr; + fn getRCodeAction(config: &RCodeActionConfiguration) -> SharedPtr; + fn getRemoteLogAction(config: &RemoteLogActionConfiguration) -> SharedPtr; + fn getSetAdditionalProxyProtocolValueAction(config: &SetAdditionalProxyProtocolValueActionConfiguration) -> SharedPtr; + fn getSetDisableECSAction(config: &SetDisableECSActionConfiguration) -> SharedPtr; + fn getSetDisableValidationAction(config: &SetDisableValidationActionConfiguration) -> SharedPtr; + fn getSetECSAction(config: &SetECSActionConfiguration) -> SharedPtr; + fn getSetECSOverrideAction(config: &SetECSOverrideActionConfiguration) -> SharedPtr; + fn getSetECSPrefixLengthAction(config: &SetECSPrefixLengthActionConfiguration) -> SharedPtr; + fn getSetExtendedDNSErrorAction(config: &SetExtendedDNSErrorActionConfiguration) -> SharedPtr; + fn getSetMacAddrAction(config: &SetMacAddrActionConfiguration) -> SharedPtr; + fn getSetMaxReturnedTTLAction(config: &SetMaxReturnedTTLActionConfiguration) -> SharedPtr; + fn getSetNoRecurseAction(config: &SetNoRecurseActionConfiguration) -> SharedPtr; + fn getSetProxyProtocolValuesAction(config: &SetProxyProtocolValuesActionConfiguration) -> SharedPtr; + fn getSetSkipCacheAction(config: &SetSkipCacheActionConfiguration) -> SharedPtr; + fn getSetTagAction(config: &SetTagActionConfiguration) -> SharedPtr; + fn getSetTempFailureCacheTTLAction(config: &SetTempFailureCacheTTLActionConfiguration) -> SharedPtr; + fn getSNMPTrapAction(config: &SNMPTrapActionConfiguration) -> SharedPtr; + fn getSpoofAction(config: &SpoofActionConfiguration) -> SharedPtr; + fn getSpoofCNAMEAction(config: &SpoofCNAMEActionConfiguration) -> SharedPtr; + fn getSpoofPacketAction(config: &SpoofPacketActionConfiguration) -> SharedPtr; + fn getSpoofRawAction(config: &SpoofRawActionConfiguration) -> SharedPtr; + fn getSpoofSVCAction(config: &SpoofSVCActionConfiguration) -> SharedPtr; + fn getTCAction(config: &TCActionConfiguration) -> SharedPtr; + fn getTeeAction(config: &TeeActionConfiguration) -> SharedPtr; + fn getAllowResponseAction(config: &AllowResponseActionConfiguration) -> SharedPtr; + fn getClearRecordTypesResponseAction(config: &ClearRecordTypesResponseActionConfiguration) -> SharedPtr; + fn getDelayResponseAction(config: &DelayResponseActionConfiguration) -> SharedPtr; + fn getDnstapLogResponseAction(config: &DnstapLogResponseActionConfiguration) -> SharedPtr; + fn getDropResponseAction(config: &DropResponseActionConfiguration) -> SharedPtr; + fn getLimitTTLResponseAction(config: &LimitTTLResponseActionConfiguration) -> SharedPtr; + fn getLogResponseAction(config: &LogResponseActionConfiguration) -> SharedPtr; + fn getLuaResponseAction(config: &LuaResponseActionConfiguration) -> SharedPtr; + fn getLuaFFIResponseAction(config: &LuaFFIResponseActionConfiguration) -> SharedPtr; + fn getLuaFFIPerThreadResponseAction(config: &LuaFFIPerThreadResponseActionConfiguration) -> SharedPtr; + fn getRemoteLogResponseAction(config: &RemoteLogResponseActionConfiguration) -> SharedPtr; + fn getSetExtendedDNSErrorResponseAction(config: &SetExtendedDNSErrorResponseActionConfiguration) -> SharedPtr; + fn getSetMaxReturnedTTLResponseAction(config: &SetMaxReturnedTTLResponseActionConfiguration) -> SharedPtr; + fn getSetMaxTTLResponseAction(config: &SetMaxTTLResponseActionConfiguration) -> SharedPtr; + fn getSetMinTTLResponseAction(config: &SetMinTTLResponseActionConfiguration) -> SharedPtr; + fn getSetReducedTTLResponseAction(config: &SetReducedTTLResponseActionConfiguration) -> SharedPtr; + fn getSetSkipCacheResponseAction(config: &SetSkipCacheResponseActionConfiguration) -> SharedPtr; + fn getSetTagResponseAction(config: &SetTagResponseActionConfiguration) -> SharedPtr; + fn getSNMPTrapResponseAction(config: &SNMPTrapResponseActionConfiguration) -> SharedPtr; + fn getTCResponseAction(config: &TCResponseActionConfiguration) -> SharedPtr; + fn getAllSelector(config: &AllSelectorConfiguration) -> SharedPtr; + fn getAndSelector(config: &AndSelectorConfiguration) -> SharedPtr; + fn getByNameSelector(config: &ByNameSelectorConfiguration) -> SharedPtr; + fn getDNSSECSelector(config: &DNSSECSelectorConfiguration) -> SharedPtr; + fn getDSTPortSelector(config: &DSTPortSelectorConfiguration) -> SharedPtr; + fn getEDNSOptionSelector(config: &EDNSOptionSelectorConfiguration) -> SharedPtr; + fn getEDNSVersionSelector(config: &EDNSVersionSelectorConfiguration) -> SharedPtr; + fn getERCodeSelector(config: &ERCodeSelectorConfiguration) -> SharedPtr; + fn getHTTPHeaderSelector(config: &HTTPHeaderSelectorConfiguration) -> SharedPtr; + fn getHTTPPathSelector(config: &HTTPPathSelectorConfiguration) -> SharedPtr; + fn getHTTPPathRegexSelector(config: &HTTPPathRegexSelectorConfiguration) -> SharedPtr; + fn getKeyValueStoreLookupSelector(config: &KeyValueStoreLookupSelectorConfiguration) -> SharedPtr; + fn getKeyValueStoreRangeLookupSelector(config: &KeyValueStoreRangeLookupSelectorConfiguration) -> SharedPtr; + fn getLuaSelector(config: &LuaSelectorConfiguration) -> SharedPtr; + fn getLuaFFISelector(config: &LuaFFISelectorConfiguration) -> SharedPtr; + fn getLuaFFIPerThreadSelector(config: &LuaFFIPerThreadSelectorConfiguration) -> SharedPtr; + fn getMaxQPSSelector(config: &MaxQPSSelectorConfiguration) -> SharedPtr; + fn getMaxQPSIPSelector(config: &MaxQPSIPSelectorConfiguration) -> SharedPtr; + fn getNetmaskGroupSelector(config: &NetmaskGroupSelectorConfiguration) -> SharedPtr; + fn getNotSelector(config: &NotSelectorConfiguration) -> SharedPtr; + fn getOpcodeSelector(config: &OpcodeSelectorConfiguration) -> SharedPtr; + fn getOrSelector(config: &OrSelectorConfiguration) -> SharedPtr; + fn getPayloadSizeSelector(config: &PayloadSizeSelectorConfiguration) -> SharedPtr; + fn getPoolAvailableSelector(config: &PoolAvailableSelectorConfiguration) -> SharedPtr; + fn getPoolOutstandingSelector(config: &PoolOutstandingSelectorConfiguration) -> SharedPtr; + fn getProbaSelector(config: &ProbaSelectorConfiguration) -> SharedPtr; + fn getProxyProtocolValueSelector(config: &ProxyProtocolValueSelectorConfiguration) -> SharedPtr; + fn getQClassSelector(config: &QClassSelectorConfiguration) -> SharedPtr; + fn getQNameSelector(config: &QNameSelectorConfiguration) -> SharedPtr; + fn getQNameLabelsCountSelector(config: &QNameLabelsCountSelectorConfiguration) -> SharedPtr; + fn getQNameSetSelector(config: &QNameSetSelectorConfiguration) -> SharedPtr; + fn getQNameSuffixSelector(config: &QNameSuffixSelectorConfiguration) -> SharedPtr; + fn getQNameWireLengthSelector(config: &QNameWireLengthSelectorConfiguration) -> SharedPtr; + fn getQTypeSelector(config: &QTypeSelectorConfiguration) -> SharedPtr; + fn getRCodeSelector(config: &RCodeSelectorConfiguration) -> SharedPtr; + fn getRDSelector(config: &RDSelectorConfiguration) -> SharedPtr; + fn getRE2Selector(config: &RE2SelectorConfiguration) -> SharedPtr; + fn getRecordsCountSelector(config: &RecordsCountSelectorConfiguration) -> SharedPtr; + fn getRecordsTypeCountSelector(config: &RecordsTypeCountSelectorConfiguration) -> SharedPtr; + fn getRegexSelector(config: &RegexSelectorConfiguration) -> SharedPtr; + fn getSNISelector(config: &SNISelectorConfiguration) -> SharedPtr; + fn getTagSelector(config: &TagSelectorConfiguration) -> SharedPtr; + fn getTCPSelector(config: &TCPSelectorConfiguration) -> SharedPtr; + fn getTrailingDataSelector(config: &TrailingDataSelectorConfiguration) -> SharedPtr; + } +// START INCLUDE ./rust-middle-in.rs + /* + * Functions callable from C++ + */ + extern "Rust" { + fn from_yaml_string(str: &str) -> Result; + } + /* + * 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, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct OrSelectorConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + selectors: Vec, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct NotSelectorConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + selector: Box, +} + +#[derive(Default, Deserialize, Serialize, Debug, PartialEq)] +#[serde(deny_unknown_fields)] +struct ContinueActionConfigurationSerde { + #[serde(default, skip_serializing_if = "crate::is_default")] + action: Box, +} + +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, + #[serde(default, skip_serializing_if = "crate::is_default")] + backends: Vec, + #[serde(default, skip_serializing_if = "crate::is_default")] + binds: Vec, + #[serde(rename = "cache-hit-response-rules", default, skip_serializing_if = "crate::is_default")] + cache_hit_response_rules: Vec, + #[serde(rename = "cache-inserted-response-rules", default, skip_serializing_if = "crate::is_default")] + cache_inserted_response_rules: Vec, + #[serde(rename = "cache-miss-rules", default, skip_serializing_if = "crate::is_default")] + cache_miss_rules: Vec, + #[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, + #[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, + #[serde(default, skip_serializing_if = "crate::is_default")] + pools: Vec, + #[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, + #[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, + #[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, + #[serde(rename = "self-answered-response-rules", default, skip_serializing_if = "crate::is_default")] + self_answered_response_rules: Vec, + #[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, + } + +#[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 { + 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 { + 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 { + 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, +) -> Vec { + let mut results: Vec = 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, +) -> Vec { + let mut results: Vec = 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, +) -> Vec { + let mut results: Vec = 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 { + let serde_config: Result = + 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