type: "String"
- name: "logger-name"
type: "String"
- - name: "alter-function"
- type: "dnsdist::actions::DnstapAlterFunction"
- rust-type: "String"
+ - name: "alter-function-name"
+ type: "String"
+ default: ""
+ - name: "alter-function-code"
+ type: "String"
+ default: ""
+ - name: "alter-function-file"
+ type: "String"
default: ""
- name: "drop"
description: "Drop the packet"
cpp-optional: false
- name: "lua"
description: "Invoke a Lua function that accepts a :class:`DNSQuestion`. The function should return a :ref:`DNSAction`. If the Lua code fails, ``ServFail`` is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::actions::LuaActionFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFI"
description: "Invoke a Lua function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return a :ref:`DNSAction`. If the Lua code fails, ``ServFail`` is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::actions::LuaActionFFIFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFIPerThread"
description: "Invoke a Lua function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return a :ref:`DNSAction`. If the Lua code fails, ``ServFail`` is returned.
The function will be invoked in a per-thread Lua state, without access to the global Lua state. All constants (:ref:`DNSQType`, :ref:`DNSRCode`, ...) are available in that per-thread context, as well as all FFI functions. Objects and their bindings that are not usable in a FFI context (:class:`DNSQuestion`, :class:`DNSDistProtoBufMessage`, :class:`PacketCache`, ...) are not available."
parameters:
- name: "logger-name"
type: "String"
- - name: "alter-function"
- type: "dnsdist::actions::ProtobufAlterFunction"
- rust-type: "String"
+ - name: "alter-function-name"
+ type: "String"
+ default: ""
+ - name: "alter-function-code"
+ type: "String"
+ default: ""
+ - name: "alter-function-file"
+ type: "String"
default: ""
- name: "server-id"
type: "String"
{
return std::shared_ptr<DNSAction>(new LogAction(fileName, binary, append, buffered, verboseOnly, includeTimestamp));
}
-std::shared_ptr<DNSAction> getLuaAction(dnsdist::actions::LuaActionFunction function)
-{
- return std::shared_ptr<DNSAction>(new LuaAction(function));
-}
-std::shared_ptr<DNSAction> getLuaFFIAction(dnsdist::actions::LuaActionFFIFunction function)
-{
- return std::shared_ptr<DNSAction>(new LuaFFIAction(function));
-}
std::shared_ptr<DNSAction> getLuaFFIPerThreadAction(const std::string& code)
{
return std::shared_ptr<DNSAction>(new LuaFFIPerThreadAction(code));
std::shared_ptr<DNSAction> getDropAction();
std::shared_ptr<DNSAction> getSetEDNSOptionAction(uint32_t code, const std::string& data);
std::shared_ptr<DNSAction> getLogAction(const std::string& fileName, bool binary, bool append, bool buffered, bool verboseOnly, bool includeTimestamp);
-std::shared_ptr<DNSAction> getLuaAction(dnsdist::actions::LuaActionFunction function);
-std::shared_ptr<DNSAction> getLuaFFIAction(dnsdist::actions::LuaActionFFIFunction function);
std::shared_ptr<DNSAction> getLuaFFIPerThreadAction(const std::string& code);
std::shared_ptr<DNSAction> getNoneAction();
std::shared_ptr<DNSAction> getPoolAction(const std::string& poolName, bool stopProcessing);
uint32_t d_max{std::numeric_limits<uint32_t>::max()};
};
+std::shared_ptr<DNSAction> getLuaAction(dnsdist::actions::LuaActionFunction function)
+{
+ return std::shared_ptr<DNSAction>(new LuaAction(function));
+}
+
+std::shared_ptr<DNSAction> getLuaFFIAction(dnsdist::actions::LuaActionFFIFunction function)
+{
+ return std::shared_ptr<DNSAction>(new LuaFFIAction(function));
+}
+
+std::shared_ptr<DNSResponseAction> getLuaResponseAction(dnsdist::actions::LuaResponseActionFunction function)
+{
+ return std::shared_ptr<DNSResponseAction>(new LuaResponseAction(function));
+}
+
+std::shared_ptr<DNSResponseAction> getLuaFFIResponseAction(dnsdist::actions::LuaResponseActionFFIFunction function)
+{
+ return std::shared_ptr<DNSResponseAction>(new LuaFFIResponseAction(function));
+}
+
#ifndef DISABLE_PROTOBUF
std::shared_ptr<DNSAction> getRemoteLogAction(RemoteLogActionConfiguration& config)
{
#include "dnsdist-actions-factory-generated.hh"
#include "dnsdist-response-actions-factory-generated.hh"
+std::shared_ptr<DNSAction> getLuaAction(dnsdist::actions::LuaActionFunction function);
+std::shared_ptr<DNSAction> getLuaFFIAction(dnsdist::actions::LuaActionFFIFunction function);
+std::shared_ptr<DNSResponseAction> getLuaResponseAction(dnsdist::actions::LuaResponseActionFunction function);
+std::shared_ptr<DNSResponseAction> getLuaFFIResponseAction(dnsdist::actions::LuaResponseActionFFIFunction function);
+
std::shared_ptr<DNSAction> getContinueAction(std::shared_ptr<DNSAction> action);
#ifdef HAVE_DNS_OVER_HTTPS
std::shared_ptr<DNSAction> getHTTPStatusAction(uint16_t status, PacketBuffer&& body, const std::string& contentType, const dnsdist::ResponseConfig& responseConfig);
return checkedConversionFromStr<T>(context, parameterName, std::string(str));
}
+template <class T>
+static bool getOptionalLuaFunction(T& destination, const ::rust::string& functionName)
+{
+ auto lua = g_lua.lock();
+ auto function = lua->readVariable<boost::optional<T>>(std::string(functionName));
+ if (!function) {
+ return false;
+ }
+ destination = *function;
+ return true;
+}
+
+static std::optional<std::string> loadContentFromConfigurationFile(const std::string& fileName)
+{
+ /* no check on the file size, don't do this with just any file! */
+ auto file = std::ifstream(fileName);
+ if (!file.is_open()) {
+ return std::nullopt;
+ }
+ return std::string(std::istreambuf_iterator<char>(file), {});
+}
+
+template <class FuncType>
+static bool getLuaFunctionFromConfiguration(FuncType& destination, const ::rust::string& functionName, const ::rust::string& functionCode, const ::rust::string& functionFile, const std::string& context)
+{
+ if (!functionName.empty()) {
+ return getOptionalLuaFunction<FuncType>(destination, functionName);
+ }
+ if (!functionCode.empty()) {
+ auto function = dnsdist::lua::getFunctionFromLuaCode<FuncType>(std::string(functionCode), context);
+ if (function) {
+ destination = *function;
+ return true;
+ }
+ throw std::runtime_error("Unable to load a Lua function from the content of lua directive in " + context + " context");
+ }
+ if (!functionFile.empty()) {
+ auto content = loadContentFromConfigurationFile(std::string(functionFile));
+ if (!content) {
+ throw std::runtime_error("Unable to load content of lua-file's '" + std::string(functionFile) + "' in " + context + " context");
+ }
+ auto function = dnsdist::lua::getFunctionFromLuaCode<FuncType>(*content, context);
+ if (function) {
+ destination = *function;
+ return true;
+ }
+ throw std::runtime_error("Unable to load a Lua function from the content of lua-file's '" + std::string(functionFile) + "' in " + context + " context");
+ }
+ return false;
+}
+
static std::set<int> getCPUPiningFromStr(const std::string& context, const std::string& cpuStr)
{
std::set<int> cpus;
return true;
}
-template <class T>
-static bool getOptionalLuaFunction(T& destination, const ::rust::string& functionName)
-{
- auto lua = g_lua.lock();
- auto function = lua->readVariable<boost::optional<T>>(std::string(functionName));
- if (!function) {
- return false;
- }
- destination = *function;
- return true;
-}
-
static std::shared_ptr<DownstreamState> createBackendFromConfiguration(const dnsdist::rust::settings::BackendConfiguration& config, bool configCheck)
{
DownstreamState::Config backendConfig;
backendConfig.maxCheckFailures = hcConf.max_failures;
backendConfig.minRiseSuccesses = hcConf.rise;
- getOptionalLuaFunction<DownstreamState::checkfunc_t>(backendConfig.checkFunction, hcConf.function);
+ getLuaFunctionFromConfiguration<DownstreamState::checkfunc_t>(backendConfig.checkFunction, hcConf.function, hcConf.lua, hcConf.lua_file, "backend health-check");
auto availability = DownstreamState::getAvailabilityFromStr(std::string(hcConf.mode));
if (availability) {
ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
}
DynBlockRulesGroup::smtVisitor_t visitor;
- getOptionalLuaFunction<DynBlockRulesGroup::smtVisitor_t>(visitor, rule.visitor_function);
+ getLuaFunctionFromConfiguration(visitor, rule.visitor_function_name, rule.visitor_function_code, rule.visitor_function_file, "dynamic block suffix match visitor function");
dbrgObj->setSuffixMatchRule(std::move(ruleParams), std::move(visitor));
}
else if (rule.rule_type == "suffix-match-ffi") {
ruleParams.d_tagSettings->d_value = std::string(rule.tag_value);
}
dnsdist_ffi_stat_node_visitor_t visitor;
- getOptionalLuaFunction<dnsdist_ffi_stat_node_visitor_t>(visitor, rule.visitor_function);
+ getLuaFunctionFromConfiguration(visitor, rule.visitor_function_name, rule.visitor_function_code, rule.visitor_function_file, "dynamic block suffix match FFI visitor function");
dbrgObj->setSuffixMatchRuleFFI(std::move(ruleParams), std::move(visitor));
}
}
config.d_apiReadWrite = webConfig.api_read_write;
});
}
-
#endif /* defined(HAVE_YAML_CONFIGURATION) */
bool loadConfigurationFromFile(const std::string& fileName, bool isClient, bool configCheck)
s_inConfigCheckMode.store(configCheck);
s_inClientMode.store(isClient);
- auto file = std::ifstream(fileName);
- if (!file.is_open()) {
+ auto data = loadContentFromConfigurationFile(fileName);
+ if (!data) {
errlog("Unable to open YAML file %s: %s", fileName, stringerror(errno));
return false;
}
}
try {
- auto data = std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
-
- auto globalConfig = dnsdist::rust::settings::from_yaml_string(data);
+ auto globalConfig = dnsdist::rust::settings::from_yaml_string(*data);
if (!globalConfig.console.listen_address.empty()) {
const auto& consoleConf = globalConfig.console;
if (globalConfig.query_count.enabled) {
dnsdist::configuration::updateRuntimeConfiguration([&globalConfig](dnsdist::configuration::RuntimeConfiguration& config) {
config.d_queryCountConfig.d_enabled = true;
- if (!globalConfig.query_count.filter.empty()) {
- getOptionalLuaFunction<dnsdist::QueryCount::Configuration::Filter>(config.d_queryCountConfig.d_filter, globalConfig.query_count.filter);
- }
+ getLuaFunctionFromConfiguration(config.d_queryCountConfig.d_filter, globalConfig.query_count.filter_function_name, globalConfig.query_count.filter_function_code, globalConfig.query_count.filter_function_file, "query count filter function");
});
}
for (const auto& policy : globalConfig.load_balancing_policies.custom_policies) {
if (policy.ffi) {
if (policy.per_thread) {
- auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::string(policy.function));
+ auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::string(policy.function_code));
registerType<ServerPolicy>(policyObj, policy.name);
}
else {
ServerPolicy::ffipolicyfunc_t function;
- if (!getOptionalLuaFunction<ServerPolicy::ffipolicyfunc_t>(function, policy.function)) {
- throw std::runtime_error("Custom FFI load-balancing policy '" + std::string(policy.name) + "' is referring to a non-existent Lua function '" + std::string(policy.function) + "'");
+ if (!getLuaFunctionFromConfiguration(function, policy.function_name, policy.function_code, policy.function_file, "FFI load-balancing policy")) {
+ throw std::runtime_error("Custom FFI load-balancing policy '" + std::string(policy.name) + "' could not be created: no valid function name, Lua code or Lua file");
}
auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::move(function));
registerType<ServerPolicy>(policyObj, policy.name);
}
else {
ServerPolicy::policyfunc_t function;
- if (!getOptionalLuaFunction<ServerPolicy::policyfunc_t>(function, policy.function)) {
- throw std::runtime_error("Custom load-balancing policy '" + std::string(policy.name) + "' is referring to a non-existent Lua function '" + std::string(policy.function) + "'");
+ if (!getLuaFunctionFromConfiguration(function, policy.function_name, policy.function_code, policy.function_file, "load-balancing policy")) {
+ throw std::runtime_error("Custom load-balancing policy '" + std::string(policy.name) + "' could not be created: no valid function name, Lua code or Lua file");
}
auto policyObj = std::make_shared<ServerPolicy>(std::string(policy.name), std::move(function), true);
registerType<ServerPolicy>(policyObj, policy.name);
return cppParameters;
}
-template <class T>
-T convertLuaFunction(const ::rust::String& context, const ::rust::String& name)
+std::shared_ptr<DNSActionWrapper> getLuaAction(const LuaActionConfiguration& config)
{
- T function;
- if (!dnsdist::configuration::yaml::getOptionalLuaFunction<T>(function, name)) {
- throw std::runtime_error("Context '" + std::string(context) + "' is referring to a non-existent Lua function '" + std::string(name) + "'");
+ dnsdist::actions::LuaActionFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua action")) {
+ throw std::runtime_error("Lua action '" + std::string(config.name) + "' could not be created: no valid function name, Lua code or Lua file");
}
- return function;
+ auto action = dnsdist::actions::getLuaAction(std::move(function));
+ return newDNSActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSActionWrapper> getLuaFFIAction(const LuaFFIActionConfiguration& config)
+{
+ dnsdist::actions::LuaActionFFIFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua action")) {
+ throw std::runtime_error("Lua FFI action '" + std::string(config.name) + "' could not be created: no valid function name, Lua code or Lua file");
+ }
+ auto action = dnsdist::actions::getLuaFFIAction(std::move(function));
+ return newDNSActionWrapper(std::move(action), config.name);
}
std::shared_ptr<DNSActionWrapper> getContinueAction(const ContinueActionConfiguration& config)
return newDNSActionWrapper(std::move(action), config.name);
}
+std::shared_ptr<DNSResponseActionWrapper> getLuaResponseAction(const LuaResponseActionConfiguration& config)
+{
+ dnsdist::actions::LuaResponseActionFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua action")) {
+ throw std::runtime_error("Lua response action '" + std::string(config.name) + "' could not be created: no valid function name, Lua code or Lua file");
+ }
+ auto action = dnsdist::actions::getLuaResponseAction(std::move(function));
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
+std::shared_ptr<DNSResponseActionWrapper> getLuaFFIResponseAction(const LuaFFIResponseActionConfiguration& config)
+{
+ dnsdist::actions::LuaResponseActionFFIFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua action")) {
+ throw std::runtime_error("Lua FFI response action '" + std::string(config.name) + "' could not be created: no valid function name, Lua code or Lua file");
+ }
+ auto action = dnsdist::actions::getLuaFFIResponseAction(std::move(function));
+ return newDNSResponseActionWrapper(std::move(action), config.name);
+}
+
std::shared_ptr<DNSResponseActionWrapper> getClearRecordTypesResponseAction(const ClearRecordTypesResponseActionConfiguration& config)
{
std::unordered_set<QType> qtypes{};
throw std::runtime_error("Unable to find the dnstap logger named '" + std::string(config.logger_name) + "'");
}
dnsdist::actions::DnstapAlterFunction alterFunc;
- dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::DnstapAlterFunction>(alterFunc, config.alter_function);
+ dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(alterFunc, config.alter_function_name, config.alter_function_code, config.alter_function_file, "dnstap log action");
auto action = dnsdist::actions::getDnstapLogAction(std::string(config.identity), logger, alterFunc);
return newDNSActionWrapper(std::move(action), config.name);
#endif
throw std::runtime_error("Unable to find the dnstap logger named '" + std::string(config.logger_name) + "'");
}
dnsdist::actions::DnstapAlterResponseFunction alterFunc;
- dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::DnstapAlterResponseFunction>(alterFunc, config.alter_function);
+ dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(alterFunc, config.alter_function_name, config.alter_function_code, config.alter_function_file, "dnstap log response action");
auto action = dnsdist::actions::getDnstapLogResponseAction(std::string(config.identity), logger, alterFunc);
return newDNSResponseActionWrapper(std::move(action), config.name);
#endif
}
}
dnsdist::actions::ProtobufAlterFunction alterFunc;
- if (dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::ProtobufAlterFunction>(alterFunc, config.alter_function)) {
+ if (dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(alterFunc, config.alter_function_name, config.alter_function_code, config.alter_function_file, "remote log action")) {
actionConfig.alterQueryFunc = std::move(alterFunc);
}
auto action = dnsdist::actions::getRemoteLogAction(actionConfig);
actionConfig.exportExtendedErrorsToMeta = std::string(config.export_extended_errors_to_meta);
}
dnsdist::actions::ProtobufAlterResponseFunction alterFunc;
- if (dnsdist::configuration::yaml::getOptionalLuaFunction<dnsdist::actions::ProtobufAlterResponseFunction>(alterFunc, config.alter_function)) {
+ if (dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(alterFunc, config.alter_function_name, config.alter_function_code, config.alter_function_file, "remote log response action")) {
actionConfig.alterResponseFunc = std::move(alterFunc);
}
auto action = dnsdist::actions::getRemoteLogResponseAction(actionConfig);
#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
}
+std::shared_ptr<DNSSelector> getLuaSelector(const LuaSelectorConfiguration& config)
+{
+ dnsdist::selectors::LuaSelectorFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua selector")) {
+ throw std::runtime_error("Unable to create a Lua selector: no valid function name, Lua code or Lua file");
+ }
+ auto selector = dnsdist::selectors::getLuaSelector(function);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
+std::shared_ptr<DNSSelector> getLuaFFISelector(const LuaFFISelectorConfiguration& config)
+{
+ dnsdist::selectors::LuaSelectorFFIFunction function;
+ if (!dnsdist::configuration::yaml::getLuaFunctionFromConfiguration(function, config.function_name, config.function_code, config.function_file, "Lua FFI selector")) {
+ throw std::runtime_error("Unable to create a Lua FFI selector: no valid function name, Lua code or Lua file");
+ }
+ auto selector = dnsdist::selectors::getLuaFFISelector(function);
+ return newDNSSelector(std::move(selector), config.name);
+}
+
std::shared_ptr<DNSSelector> getAndSelector(const AndSelectorConfiguration& config)
{
std::vector<std::shared_ptr<DNSRule>> selectors;
luaCtx.writeFunction("LogAction", [](boost::optional<std::string> fileName, boost::optional<bool> binary, boost::optional<bool> append, boost::optional<bool> buffered, boost::optional<bool> verboseOnly, boost::optional<bool> includeTimestamp) {
return dnsdist::actions::getLogAction(fileName ? *fileName : "", binary ? *binary : true, append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false);
});
-luaCtx.writeFunction("LuaAction", [](dnsdist::actions::LuaActionFunction function) {
- return dnsdist::actions::getLuaAction(function);
-});
-luaCtx.writeFunction("LuaFFIAction", [](dnsdist::actions::LuaActionFFIFunction function) {
- return dnsdist::actions::getLuaFFIAction(function);
-});
luaCtx.writeFunction("LuaFFIPerThreadAction", [](std::string code) {
return dnsdist::actions::getLuaFFIPerThreadAction(code);
});
luaCtx.registerFunction("reload", &DNSAction::reload);
luaCtx.registerFunction("reload", &DNSResponseAction::reload);
+ luaCtx.writeFunction("LuaAction", [](dnsdist::actions::LuaActionFunction function) {
+ return dnsdist::actions::getLuaAction(function);
+ });
+
+ luaCtx.writeFunction("LuaFFIAction", [](dnsdist::actions::LuaActionFFIFunction function) {
+ return dnsdist::actions::getLuaFFIAction(function);
+ });
+
+ luaCtx.writeFunction("LuaResponseAction", [](dnsdist::actions::LuaResponseActionFunction function) {
+ return dnsdist::actions::getLuaResponseAction(function);
+ });
+
+ luaCtx.writeFunction("LuaFFIResponseAction", [](dnsdist::actions::LuaResponseActionFFIFunction function) {
+ return dnsdist::actions::getLuaFFIResponseAction(function);
+ });
+
luaCtx.writeFunction("SpoofAction", [](LuaTypeOrArrayOf<std::string> inp, boost::optional<responseParams_t> vars) {
vector<ComboAddress> addrs;
if (auto* ipaddr = boost::get<std::string>(&inp)) {
luaCtx.writeFunction("LogResponseAction", [](boost::optional<std::string> fileName, boost::optional<bool> append, boost::optional<bool> buffered, boost::optional<bool> verboseOnly, boost::optional<bool> includeTimestamp) {
return dnsdist::actions::getLogResponseAction(fileName ? *fileName : "", append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false);
});
-luaCtx.writeFunction("LuaResponseAction", [](dnsdist::actions::LuaResponseActionFunction function) {
- return dnsdist::actions::getLuaResponseAction(function);
-});
-luaCtx.writeFunction("LuaFFIResponseAction", [](dnsdist::actions::LuaResponseActionFFIFunction function) {
- return dnsdist::actions::getLuaFFIResponseAction(function);
-});
luaCtx.writeFunction("LuaFFIPerThreadResponseAction", [](std::string code) {
return dnsdist::actions::getLuaFFIPerThreadResponseAction(code);
});
return std::shared_ptr<DNSRule>(new NotRule(rule));
});
+ luaCtx.writeFunction("LuaRule", [](dnsdist::selectors::LuaSelectorFunction function) {
+ return std::shared_ptr<DNSRule>(dnsdist::selectors::getLuaSelector(function));
+ });
+
+ luaCtx.writeFunction("LuaFFIRule", [](dnsdist::selectors::LuaSelectorFFIFunction function) {
+ return std::shared_ptr<DNSRule>(dnsdist::selectors::getLuaFFISelector(function));
+ });
+
luaCtx.writeFunction("RCodeRule", [](uint64_t rcode) {
checkParameterBound("RCodeRule", rcode, std::numeric_limits<uint8_t>::max());
return std::shared_ptr<DNSRule>(new RCodeRule(rcode));
luaCtx.writeFunction("HTTPPathRegexRule", [](std::string expression) {
return std::shared_ptr<DNSRule>(dnsdist::selectors::getHTTPPathRegexSelector(expression));
});
-luaCtx.writeFunction("LuaRule", [](dnsdist::selectors::LuaSelectorFunction function) {
- return std::shared_ptr<DNSRule>(dnsdist::selectors::getLuaSelector(function));
-});
-luaCtx.writeFunction("LuaFFIRule", [](dnsdist::selectors::LuaSelectorFFIFunction function) {
- return std::shared_ptr<DNSRule>(dnsdist::selectors::getLuaFFISelector(function));
-});
luaCtx.writeFunction("LuaFFIPerThreadRule", [](std::string code) {
return std::shared_ptr<DNSRule>(dnsdist::selectors::getLuaFFIPerThreadSelector(code));
});
{
void setupLua(LuaContext& luaCtx, bool client, bool configCheck);
void setupConfigurationItems(LuaContext& luaCtx);
+
+template <class FunctionType>
+std::optional<FunctionType> getFunctionFromLuaCode(const std::string& code, const std::string& context)
+{
+ try {
+ auto function = g_lua.lock()->executeCode<FunctionType>(code);
+ if (!function) {
+ return std::nullopt;
+ }
+ return function;
+ }
+ catch (const std::exception& exp) {
+ warnlog("Parsing Lua code '%s' in context '%s' failed: %s", code, context, exp.what());
+ }
+
+ return std::nullopt;
+}
}
namespace dnsdist::configuration::lua
type: "String"
- name: "logger-name"
type: "String"
- - name: "alter-function"
- type: "dnsdist::actions::DnstapAlterResponseFunction"
- rust-type: "String"
+ - name: "alter-function_name"
+ type: "String"
+ default: ""
+ - name: "alter-function-code"
+ type: "String"
+ default: ""
+ - name: "alter-function-file"
+ type: "String"
default: ""
- name: "drop"
description: "Drop the packet"
cpp-optional: false
- name: "lua"
description: "Invoke a Lua function that accepts a :class:`DNSResponse`. The function should return a :ref:`DNSResponseAction`. If the Lua code fails, ``ServFail`` is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::actions::LuaResponseActionFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFI"
description: "Invoke a Lua function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return a :ref:`DNSResponseAction`. If the Lua code fails, ``ServFail`` is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::actions::LuaResponseActionFFIFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFIPerThread"
description: "Invoke a Lua function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return a :ref:`DNSResponseAction`. If the Lua code fails, ``ServFail`` is returned.
The function will be invoked in a per-thread Lua state, without access to the global Lua state. All constants (:ref:`DNSQType`, :ref:`DNSRCode`, ...) are available in that per-thread context, as well as all FFI functions. Objects and their bindings that are not usable in a FFI context (:class:`DNSQuestion`, :class:`DNSDistProtoBufMessage`, :class:`PacketCache`, ...) are not available."
parameters:
- name: "logger-name"
type: "String"
- - name: "alter-function"
- type: "dnsdist::actions::ProtobufAlterResponseFunction"
- rust-type: "String"
+ - name: "alter-function-name"
+ type: "String"
+ default: ""
+ - name: "alter-function-code"
+ type: "String"
+ default: ""
+ - name: "alter-function-file"
+ type: "String"
default: ""
- name: "server-id"
type: "String"
{
return std::shared_ptr<DNSResponseAction>(new LogResponseAction(fileName, append, buffered, verboseOnly, includeTimestamp));
}
-std::shared_ptr<DNSResponseAction> getLuaResponseAction(dnsdist::actions::LuaResponseActionFunction function)
-{
- return std::shared_ptr<DNSResponseAction>(new LuaResponseAction(function));
-}
-std::shared_ptr<DNSResponseAction> getLuaFFIResponseAction(dnsdist::actions::LuaResponseActionFFIFunction function)
-{
- return std::shared_ptr<DNSResponseAction>(new LuaFFIResponseAction(function));
-}
std::shared_ptr<DNSResponseAction> getLuaFFIPerThreadResponseAction(const std::string& code)
{
return std::shared_ptr<DNSResponseAction>(new LuaFFIPerThreadResponseAction(code));
std::shared_ptr<DNSResponseAction> getDelayResponseAction(uint32_t msec);
std::shared_ptr<DNSResponseAction> getDropResponseAction();
std::shared_ptr<DNSResponseAction> getLogResponseAction(const std::string& fileName, bool append, bool buffered, bool verboseOnly, bool includeTimestamp);
-std::shared_ptr<DNSResponseAction> getLuaResponseAction(dnsdist::actions::LuaResponseActionFunction function);
-std::shared_ptr<DNSResponseAction> getLuaFFIResponseAction(dnsdist::actions::LuaResponseActionFFIFunction function);
std::shared_ptr<DNSResponseAction> getLuaFFIPerThreadResponseAction(const std::string& code);
std::shared_ptr<DNSResponseAction> getSetExtendedDNSErrorResponseAction(uint16_t infoCode, const std::string& extraText);
std::shared_ptr<DNSResponseAction> getSetReducedTTLResponseAction(uint8_t percentage);
std::shared_ptr<AndRule> getAndSelector(const std::vector<std::shared_ptr<DNSRule>>& rules);
std::shared_ptr<OrRule> getOrSelector(const std::vector<std::shared_ptr<DNSRule>>& rules);
std::shared_ptr<NotRule> getNotSelector(const std::shared_ptr<DNSRule>& rule);
+std::shared_ptr<LuaRule> getLuaSelector(const dnsdist::selectors::LuaSelectorFunction& func);
+std::shared_ptr<LuaFFIRule> getLuaFFISelector(const dnsdist::selectors::LuaSelectorFFIFunction& func);
std::shared_ptr<QNameRule> getQNameSelector(const DNSName& qname);
std::shared_ptr<QNameSetRule> getQNameSetSelector(const DNSNameSet& qnames);
std::shared_ptr<SuffixMatchNodeRule> getQNameSuffixSelector(const SuffixMatchNode& suffixes, bool quiet);
# 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' 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-cpp' means that the corresponding C++ factory and Lua bindings will not be generated, which is useful for objects taking parameters that cannot be directly mapped
# - 'skip-rust' is not used by this script but is used by the dnsdist-settings-generator.py one, where it means that the C++ code to create the Rust-side version of an action or selector will not generated
# - 'skip-serde' is not used by this script but is used by the dnsdist-settings-generator.py one, where it 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.
import os
return std::make_shared<NotRule>(rule);
}
+std::shared_ptr<LuaRule> getLuaSelector(const dnsdist::selectors::LuaSelectorFunction& func)
+{
+ return std::make_shared<LuaRule>(func);
+}
+
+std::shared_ptr<LuaFFIRule> getLuaFFISelector(const dnsdist::selectors::LuaSelectorFFIFunction& func)
+{
+ return std::make_shared<LuaFFIRule>(func);
+}
+
// NOLINTNEXTLINE(bugprone-suspicious-include)
#include "dnsdist-selectors-factory-generated.cc"
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<DNSActionWrapper> getLuaAction(const LuaActionConfiguration& config)
-{
- auto action = dnsdist::actions::getLuaAction(convertLuaFunction<dnsdist::actions::LuaActionFunction>("LuaActionConfiguration", config.function));
- return newDNSActionWrapper(std::move(action), config.name);
-}
-std::shared_ptr<DNSActionWrapper> getLuaFFIAction(const LuaFFIActionConfiguration& config)
-{
- auto action = dnsdist::actions::getLuaFFIAction(convertLuaFunction<dnsdist::actions::LuaActionFFIFunction>("LuaFFIActionConfiguration", config.function));
- return newDNSActionWrapper(std::move(action), config.name);
-}
std::shared_ptr<DNSActionWrapper> getLuaFFIPerThreadAction(const LuaFFIPerThreadActionConfiguration& config)
{
auto action = dnsdist::actions::getLuaFFIPerThreadAction(std::string(config.code));
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<DNSResponseActionWrapper> getLuaResponseAction(const LuaResponseActionConfiguration& config)
-{
- auto action = dnsdist::actions::getLuaResponseAction(convertLuaFunction<dnsdist::actions::LuaResponseActionFunction>("LuaResponseActionConfiguration", config.function));
- return newDNSResponseActionWrapper(std::move(action), config.name);
-}
-std::shared_ptr<DNSResponseActionWrapper> getLuaFFIResponseAction(const LuaFFIResponseActionConfiguration& config)
-{
- auto action = dnsdist::actions::getLuaFFIResponseAction(convertLuaFunction<dnsdist::actions::LuaResponseActionFFIFunction>("LuaFFIResponseActionConfiguration", config.function));
- return newDNSResponseActionWrapper(std::move(action), config.name);
-}
std::shared_ptr<DNSResponseActionWrapper> getLuaFFIPerThreadResponseAction(const LuaFFIPerThreadResponseActionConfiguration& config)
{
auto action = dnsdist::actions::getLuaFFIPerThreadResponseAction(std::string(config.code));
auto selector = dnsdist::selectors::getHTTPPathRegexSelector(std::string(config.expression));
return newDNSSelector(std::move(selector), config.name);
}
-std::shared_ptr<DNSSelector> getLuaSelector(const LuaSelectorConfiguration& config)
-{
- auto selector = dnsdist::selectors::getLuaSelector(convertLuaFunction<dnsdist::selectors::LuaSelectorFunction>("LuaSelectorConfiguration", config.function));
- return newDNSSelector(std::move(selector), config.name);
-}
-std::shared_ptr<DNSSelector> getLuaFFISelector(const LuaFFISelectorConfiguration& config)
-{
- auto selector = dnsdist::selectors::getLuaFFISelector(convertLuaFunction<dnsdist::selectors::LuaSelectorFFIFunction>("LuaFFISelectorConfiguration", config.function));
- return newDNSSelector(std::move(selector), config.name);
-}
std::shared_ptr<DNSSelector> getLuaFFIPerThreadSelector(const LuaFFIPerThreadSelectorConfiguration& config)
{
auto selector = dnsdist::selectors::getLuaFFIPerThreadSelector(std::string(config.code));
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
identity: String,
#[serde(rename = "logger-name", )]
logger_name: String,
- #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
- alter_function: String,
+ #[serde(rename = "alter-function-name", default, skip_serializing_if = "crate::is_default")]
+ alter_function_name: String,
+ #[serde(rename = "alter-function-code", default, skip_serializing_if = "crate::is_default")]
+ alter_function_code: String,
+ #[serde(rename = "alter-function-file", default, skip_serializing_if = "crate::is_default")]
+ alter_function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct LuaActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct LuaFFIActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
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 = "alter-function-name", default, skip_serializing_if = "crate::is_default")]
+ alter_function_name: String,
+ #[serde(rename = "alter-function-code", default, skip_serializing_if = "crate::is_default")]
+ alter_function_code: String,
+ #[serde(rename = "alter-function-file", default, skip_serializing_if = "crate::is_default")]
+ alter_function_file: 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")]
identity: String,
#[serde(rename = "logger-name", )]
logger_name: String,
- #[serde(rename = "alter-function", default, skip_serializing_if = "crate::is_default")]
- alter_function: String,
+ #[serde(rename = "alter-function_name", default, skip_serializing_if = "crate::is_default")]
+ alter_function_name: String,
+ #[serde(rename = "alter-function-code", default, skip_serializing_if = "crate::is_default")]
+ alter_function_code: String,
+ #[serde(rename = "alter-function-file", default, skip_serializing_if = "crate::is_default")]
+ alter_function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct LuaResponseActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct LuaFFIResponseActionConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
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 = "alter-function-name", default, skip_serializing_if = "crate::is_default")]
+ alter_function_name: String,
+ #[serde(rename = "alter-function-code", default, skip_serializing_if = "crate::is_default")]
+ alter_function_code: String,
+ #[serde(rename = "alter-function-file", default, skip_serializing_if = "crate::is_default")]
+ alter_function_file: 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")]
struct LuaSelectorConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct LuaFFISelectorConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
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(rename = "visitor-function-name", default, skip_serializing_if = "crate::is_default")]
+ visitor_function_name: String,
+ #[serde(rename = "visitor-function-code", default, skip_serializing_if = "crate::is_default")]
+ visitor_function_code: String,
+ #[serde(rename = "visitor-function-file", default, skip_serializing_if = "crate::is_default")]
+ visitor_function_file: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
rcode: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
qtype: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
function: String,
+ #[serde(default, skip_serializing_if = "crate::is_default")]
+ lua: String,
+ #[serde(rename = "lua-file", default, skip_serializing_if = "crate::is_default")]
+ lua_file: 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")]
struct QueryCountConfiguration {
#[serde(default, skip_serializing_if = "crate::is_default")]
enabled: bool,
- #[serde(default, skip_serializing_if = "crate::is_default")]
- filter: String,
+ #[serde(rename = "filter-function-name", default, skip_serializing_if = "crate::is_default")]
+ filter_function_name: String,
+ #[serde(rename = "filter-function-code", default, skip_serializing_if = "crate::is_default")]
+ filter_function_code: String,
+ #[serde(rename = "filter-function-file", default, skip_serializing_if = "crate::is_default")]
+ filter_function_file: String,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
struct CustomLoadBalancingPolicyConfiguration {
name: String,
- function: String,
+ #[serde(rename = "function-name", default, skip_serializing_if = "crate::is_default")]
+ function_name: String,
+ #[serde(rename = "function-code", default, skip_serializing_if = "crate::is_default")]
+ function_code: String,
+ #[serde(rename = "function-file", default, skip_serializing_if = "crate::is_default")]
+ function_file: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
ffi: bool,
#[serde(rename = "per-thread", default, skip_serializing_if = "crate::is_default")]
type: "String"
- name: "lua"
description: "Invoke a Lua function that accepts a :class:`DNSQuestion` object. The function should return true if the query matches, or false otherwise. If the Lua code fails, false is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::selectors::LuaSelectorFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFI"
description: "Invoke a Lua FFI function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return true if the query matches, or false otherwise. If the Lua code fails, false is returned"
+ skip-cpp: true
+ skip-rust: true
parameters:
- - name: "function"
- type: "dnsdist::selectors::LuaSelectorFFIFunction"
- rust-type: "String"
+ - name: "function-name"
+ type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "LuaFFIPerThread"
description: "Invoke a Lua FFI function that accepts a pointer to a ``dnsdist_ffi_dnsquestion_t`` object, whose bindings are defined in ``dnsdist-lua-ffi-interface.h``. The function should return true if the query matches, or false otherwise. If the Lua code fails, false is returned.
{
return std::make_shared<HTTPPathRegexRule>(expression);
}
-std::shared_ptr<LuaRule> getLuaSelector(dnsdist::selectors::LuaSelectorFunction function)
-{
- return std::make_shared<LuaRule>(function);
-}
-std::shared_ptr<LuaFFIRule> getLuaFFISelector(dnsdist::selectors::LuaSelectorFFIFunction function)
-{
- return std::make_shared<LuaFFIRule>(function);
-}
std::shared_ptr<LuaFFIPerThreadRule> getLuaFFIPerThreadSelector(const std::string& code)
{
return std::make_shared<LuaFFIPerThreadRule>(code);
std::shared_ptr<HTTPHeaderRule> getHTTPHeaderSelector(const std::string& header, const std::string& expression);
std::shared_ptr<HTTPPathRule> getHTTPPathSelector(const std::string& path);
std::shared_ptr<HTTPPathRegexRule> getHTTPPathRegexSelector(const std::string& expression);
-std::shared_ptr<LuaRule> getLuaSelector(dnsdist::selectors::LuaSelectorFunction function);
-std::shared_ptr<LuaFFIRule> getLuaFFISelector(dnsdist::selectors::LuaSelectorFFIFunction function);
std::shared_ptr<LuaFFIPerThreadRule> getLuaFFIPerThreadSelector(const std::string& code);
std::shared_ptr<MaxQPSRule> getMaxQPSSelector(uint32_t qps, std::optional<uint32_t> burst);
std::shared_ptr<MaxQPSIPRule> getMaxQPSIPSelector(uint32_t qps, std::optional<uint8_t> ipv4Mask, std::optional<uint8_t> ipv6Mask, std::optional<uint32_t> burst, std::optional<uint32_t> expiration, std::optional<uint32_t> cleanupDelay, std::optional<uint32_t> scanFraction, std::optional<uint32_t> shards);
- name: "tag-value"
type: "String"
default: "0"
- - name: "visitor-function"
+ - name: "visitor-function-name"
+ type: "String"
+ default: ""
+ - name: "visitor-function-code"
+ type: "String"
+ default: ""
+ - name: "visitor-function-file"
type: "String"
default: ""
- name: "rcode"
- name: "function"
type: "String"
default: ""
+ - name: "lua"
+ type: "String"
+ default: ""
+ - name: "lua-file"
+ type: "String"
+ default: ""
- name: "timeout"
type: "u16"
default: 1000
- name: "enabled"
type: "bool"
default: "false"
- - name: "filter"
+ - name: "filter-function-name"
+ type: "String"
+ default: ""
+ - name: "filter-function-code"
+ type: "String"
+ default: ""
+ - name: "filter-function-file"
type: "String"
default: ""
parameters:
- name: "name"
type: "String"
- - name: "function"
+ - name: "function-name"
type: "String"
+ default: ""
+ - name: "function-code"
+ type: "String"
+ default: ""
+ - name: "function-file"
+ type: "String"
+ default: ""
- name: "ffi"
type: "bool"
default: "false"
- **identity**: String
- **logger-name**: String
-- **alter-function**: String ``("")``
+- **alter-function-name**: String ``("")``
+- **alter-function-code**: String ``("")``
+- **alter-function-file**: String ``("")``
.. _yaml-settings-DropAction:
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFIAction:
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFIPerThreadAction:
Parameters:
- **logger-name**: String
-- **alter-function**: String ``("")``
+- **alter-function-name**: String ``("")``
+- **alter-function-code**: String ``("")``
+- **alter-function-file**: String ``("")``
- **server-id**: String ``("")``
- **ip-encrypt-key**: String ``("")``
- **export-tags**: Sequence of String
- **identity**: String
- **logger-name**: String
-- **alter-function**: String ``("")``
+- **alter-function_name**: String ``("")``
+- **alter-function-code**: String ``("")``
+- **alter-function-file**: String ``("")``
.. _yaml-settings-DropResponseAction:
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFIResponseAction:
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFIPerThreadResponseAction:
Parameters:
- **logger-name**: String
-- **alter-function**: String ``("")``
+- **alter-function-name**: String ``("")``
+- **alter-function-code**: String ``("")``
+- **alter-function-file**: String ``("")``
- **server-id**: String ``("")``
- **ip-encrypt-key**: String ``("")``
- **include-cname**: Boolean ``(false)``
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFISelector:
Parameters:
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
.. _yaml-settings-LuaFFIPerThreadSelector:
--------------------------------------
- **name**: String
-- **function**: String
+- **function-name**: String ``("")``
+- **function-code**: String ``("")``
+- **function-file**: String ``("")``
- **ffi**: Boolean ``(false)``
- **per-thread**: Boolean ``(false)``
- **warning-ratio**: Double ``(0.0)``
- **tag-name**: String ``("")``
- **tag-value**: String ``(0)``
-- **visitor-function**: String ``("")``
+- **visitor-function-name**: String ``("")``
+- **visitor-function-code**: String ``("")``
+- **visitor-function-file**: String ``("")``
- **rcode**: String ``("")``
- **qtype**: String ``("")``
- **minimum-number-of-responses**: Unsigned integer ``(0)``
- **qclass**: String ``(IN)``
- **qtype**: String ``(A)``
- **function**: String ``("")``
+- **lua**: String ``("")``
+- **lua-file**: String ``("")``
- **timeout**: Unsigned integer ``(1000)``
- **set-cd**: Boolean ``(false)``
- **max-failures**: Unsigned integer ``(1)``
-----------------------
- **enabled**: Boolean ``(false)``
-- **filter**: String ``("")``
+- **filter-function-name**: String ``("")``
+- **filter-function-code**: String ``("")``
+- **filter-function-file**: String ``("")``
.. _yaml-settings-QueryRuleConfiguration:
qname: "udp.protocols.dnscrypt.tests.powerdns.com."
action:
type: "Lua"
- function: "checkDNSCryptUDP"
+ function-name: "checkDNSCryptUDP"
- selector:
type: "QName"
qname: "tcp.protocols.dnscrypt.tests.powerdns.com."
action:
type: "Lua"
- function: "checkDNSCryptTCP"
+ function-name: "checkDNSCryptTCP"
"""
_config_params = []
_yaml_config_params = ['_consoleKeyB64', '_consolePort', '_dnsDistPortDNSCrypt', '_providerName', '_testServerPort']
qname: "http-lua.doh.tests.powerdns.com."
action:
type: "Lua"
- function: "dohHandler"
+ function-name: "dohHandler"
"""
_yaml_config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort', '_dohServerPort', '_serverCert', '_serverKey', '_dohLibrary']
_config_template = """
protocol: Do53
pools:
- "tcp-pool"
+ - "inline"
pools:
- name: "tcp-pool"
tcp: true
query-rules:
+ - name: "route inline-yaml to inline pool"
+ selector:
+ type: "QNameSet"
+ qnames:
+ - "inline-lua.yaml.test.powerdns.com."
+ action:
+ type: "Pool"
+ pool-name: "inline"
+ stop-processing: true
- name: "my-rule"
selector:
type: "And"
action:
type: "Pool"
pool-name: "tcp-pool"
+
+response-rules:
+ - name: "inline RD=0 TCP gets cleared"
+ selector:
+ type: "And"
+ selectors:
+ - type: "ByName"
+ selector-name: "is-tcp"
+ - type: "QNameSet"
+ qnames:
+ - "inline-lua.yaml.test.powerdns.com."
+ - type: "Lua"
+ name: "Match responses on RD=0 (inline)"
+ function-code: |
+ return function(dr)
+ local rd = dr.dh:getRD()
+ if not rd then
+ return true
+ end
+ return false
+ end
+ action:
+ type: "ClearRecordTypes"
+ types:
+ - 1
+ - name: "inline RD=0 UDP gets truncated"
+ selector:
+ type: "And"
+ selectors:
+ - type: "QNameSet"
+ qnames:
+ - "inline-lua.yaml.test.powerdns.com."
+ - type: "Lua"
+ name: "Match responses on RD=0 (file)"
+ function-file: "yaml-config-files/yaml-inline-lua-file.yml"
+ action:
+ type: "TC"
"""
_webServerPort = pickAvailablePort()
_dnsDistPort = pickAvailablePort()
receivedQuery.id = query.id
self.assertEqual(receivedQuery, query)
self.assertEqual(receivedResponse, response)
+
+ def testInlineLua(self):
+ """
+ Yaml: Inline Lua
+ """
+ name = 'inline-lua.yaml.test.powerdns.com.'
+
+ query = dns.message.make_query(name, 'A', 'IN')
+ query.flags &= ~dns.flags.RD
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '127.0.0.1')
+
+ response.answer.append(rrset)
+ truncatedResponse = dns.message.make_response(query)
+ truncatedResponse.flags |= dns.flags.TC
+ clearedResponse = dns.message.make_response(query)
+
+ # UDP response without RD should be truncated
+ (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response=response)
+ receivedQuery.id = query.id
+ self.assertEqual(receivedQuery, query)
+ self.assertEqual(receivedResponse, truncatedResponse)
+
+ # TCP response should have its A records cleared
+ (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response=response)
+ receivedQuery.id = query.id
+ self.assertEqual(receivedQuery, query)
+ self.assertEqual(receivedResponse, clearedResponse)
+
+ # response with RD should be forwarded
+ query = dns.message.make_query(name, 'A', 'IN')
+ query.flags |= dns.flags.RD
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '127.0.0.1')
+
+ response.answer.append(rrset)
+ for method in ["sendUDPQuery", "sendTCPQuery"]:
+ sender = getattr(self, method)
+ (receivedQuery, receivedResponse) = sender(query, response=response)
+ receivedQuery.id = query.id
+ self.assertEqual(receivedQuery, query)
+ self.assertEqual(receivedResponse, response)
--- /dev/null
+return function(dr)
+ local rd = dr.dh:getRD()
+ if not rd then
+ return true
+ end
+ return false
+end