return std::shared_ptr<DNSRule>(new QNameSetRule(names));
});
+ luaCtx.writeFunction("TagRule", [](std::string tag, boost::optional<std::string> value) {
+ return std::shared_ptr<DNSRule>(dnsdist::selectors::getTagSelector(tag, boostToStandardOptional(value), value ? false : true));
+ });
+
#if defined(HAVE_LMDB) || defined(HAVE_CDB)
luaCtx.writeFunction("KeyValueStoreLookupRule", [](std::shared_ptr<KeyValueStore>& kvs, std::shared_ptr<KeyValueLookupKey>& lookupKey) {
return std::shared_ptr<DNSRule>(new KeyValueStoreLookupRule(kvs, lookupKey));
luaCtx.writeFunction("SNIRule", [](std::string server_name) {
return std::shared_ptr<DNSRule>(dnsdist::selectors::getSNISelector(server_name));
});
-luaCtx.writeFunction("TagRule", [](std::string tag, boost::optional<std::string> value) {
- return std::shared_ptr<DNSRule>(dnsdist::selectors::getTagSelector(tag, boostToStandardOptional(value)));
-});
luaCtx.writeFunction("TCPRule", [](bool tcp) {
return std::shared_ptr<DNSRule>(dnsdist::selectors::getTCPSelector(tcp));
});
class TagRule : public DNSRule
{
public:
- TagRule(const std::string& tag, boost::optional<std::string> value) :
- d_value(std::move(value)), d_tag(tag)
+ TagRule(const std::string& tag, boost::optional<std::string> value, bool emptyAsWildcard) :
+ d_value(std::move(value)), d_tag(tag), d_emptyAsWildcard(emptyAsWildcard)
{
}
bool matches(const DNSQuestion* dq) const override
return false;
}
- if (!d_value || d_value->empty()) {
+ if (!d_value || (d_emptyAsWildcard && d_value->empty())) {
return true;
}
string toString() const override
{
- return "tag '" + d_tag + "' is set" + (d_value ? (" to '" + *d_value + "'") : "");
+ return "tag '" + d_tag + "' is set" + ((d_value && (!d_value->empty() || !d_emptyAsWildcard)) ? (" to '" + *d_value + "'") : "");
}
private:
boost::optional<std::string> d_value;
std::string d_tag;
+ bool d_emptyAsWildcard;
};
class PoolAvailableRule : public DNSRule
# 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-lua' means that the corresponding Lua bindings 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.
for action in definitions:
if 'skip-cpp' in action and action['skip-cpp']:
continue
+ if 'skip-lua' in action and action['skip-lua']:
+ continue
name = get_cpp_object_name(action['name'])
output = f'luaCtx.writeFunction("{name}{suffix}", []('
if 'parameters' in action:
for selector in definitions:
if 'skip-cpp' in selector and selector['skip-cpp']:
continue
+ if 'skip-lua' in action and action['skip-lua']:
+ continue
name = get_cpp_object_name(selector['name'])
output = f'luaCtx.writeFunction("{name}Rule", []('
if 'parameters' in selector:
}
std::shared_ptr<DNSSelector> getTagSelector(const TagSelectorConfiguration& config)
{
- auto selector = dnsdist::selectors::getTagSelector(std::string(config.tag), std::string(config.value));
+ auto selector = dnsdist::selectors::getTagSelector(std::string(config.tag), std::string(config.value), config.empty_as_wildcard);
return newDNSSelector(std::move(selector), config.name);
}
std::shared_ptr<DNSSelector> getTCPSelector(const TCPSelectorConfiguration& config)
tag: String,
#[serde(default, skip_serializing_if = "crate::is_default")]
value: String,
+ #[serde(rename = "empty-as-wildcard", default = "crate::Bool::<true>::value", skip_serializing_if = "crate::if_true")]
+ empty_as_wildcard: bool,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
description: "The exact Server Name Indication value"
- name: "Tag"
description: "Matches question or answer with a tag named ``tag`` set. If ``value`` is specified, the existing tag value should match too"
+ skip-lua: true
parameters:
- name: "tag"
type: "String"
type: "String"
default: ""
description: "If set, the value the tag has to be set to"
+ - name: "empty-as-wildcard"
+ type: "bool"
+ default: "true"
+ description: "Because of a limitation in our Rust <-> C++ interoperability layer, ``value`` defaults to an empty string, which makes it impossible to express whether an empty ``value`` means that we should match on all values (so as long as the tag has been set) or only if the value is actually empty. This flag fixes that: if ``value`` is empty and this parameter is set to ``false`` the selector will only match if the actual value of the tag is empty, while if it set to ``true`` (default) it will match as long as the tag is set, regardless of the value"
- name: "TCP"
description: "Matches question received over TCP if ``tcp`` is true, over UDP otherwise"
parameters:
{
return std::make_shared<SNIRule>(server_name);
}
-std::shared_ptr<TagRule> getTagSelector(const std::string& tag, std::optional<std::string> value)
+std::shared_ptr<TagRule> getTagSelector(const std::string& tag, std::optional<std::string> value, std::optional<bool> emptyAsWildcard)
{
- return std::make_shared<TagRule>(tag, value ? *value : "");
+ return std::make_shared<TagRule>(tag, value ? *value : "", emptyAsWildcard ? *emptyAsWildcard : true);
}
std::shared_ptr<TCPRule> getTCPSelector(bool tcp)
{
std::shared_ptr<RecordsTypeCountRule> getRecordsTypeCountSelector(uint8_t section, uint16_t record_type, uint16_t minimum, uint16_t maximum);
std::shared_ptr<RegexRule> getRegexSelector(const std::string& expression);
std::shared_ptr<SNIRule> getSNISelector(const std::string& server_name);
-std::shared_ptr<TagRule> getTagSelector(const std::string& tag, std::optional<std::string> value);
+std::shared_ptr<TagRule> getTagSelector(const std::string& tag, std::optional<std::string> value, std::optional<bool> emptyAsWildcard);
std::shared_ptr<TCPRule> getTCPSelector(bool tcp);
std::shared_ptr<TrailingDataRule> getTrailingDataSelector();