return 0;
}
-static bool net_condition_test_strv(char * const *raw_patterns,
- const char *string) {
- if (strv_isempty(raw_patterns))
+static bool net_condition_test_strv(char * const *patterns, const char *string) {
+ char * const *p;
+ bool match = false, has_positive_rule = false;
+
+ if (strv_isempty(patterns))
return true;
- /* If the patterns begin with "!", edit it out and negate the test. */
- if (raw_patterns[0][0] == '!') {
- char **patterns;
- size_t i, length;
+ STRV_FOREACH(p, patterns) {
+ const char *q = *p;
+ bool invert;
+
+ invert = *q == '!';
+ q += invert;
- length = strv_length(raw_patterns) + 1; /* Include the NULL. */
- patterns = newa(char*, length);
- patterns[0] = raw_patterns[0] + 1; /* Skip the "!". */
- for (i = 1; i < length; i++)
- patterns[i] = raw_patterns[i];
+ if (!invert)
+ has_positive_rule = true;
- return !string || !strv_fnmatch(patterns, string, 0);
+ if (string && fnmatch(q, string, 0) == 0) {
+ if (invert)
+ return false;
+ else
+ match = true;
+ }
}
- return string && strv_fnmatch(raw_patterns, string, 0);
+ return has_positive_rule ? match : true;
}
bool net_match_config(Set *match_mac,
return 0;
}
-int config_parse_ifnames(
+int config_parse_match_strv(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
+ const char *p = rvalue;
char ***sv = data;
+ bool invert;
int r;
assert(filename);
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ *sv = strv_free(*sv);
+ return 0;
+ }
+
+ invert = *p == '!';
+ p += invert;
+
for (;;) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, 0);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
+}
+
+int config_parse_match_ifnames(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
- break;
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Failed to parse interface name list: %s", rvalue);
+ return 0;
+ }
if (!ifname_valid(word)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
- return 0;
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Interface name is not valid or too long, ignoring assignment: %s", word);
+ continue;
}
- r = strv_push(sv, word);
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
-
- word = NULL;
}
-
- return 0;
}
int config_parse_ifalias(const char *unit,
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
-CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac)
-Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
-Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name)
+Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
+Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
+Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)
+Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
assert_se(network = new0(Network, 1));
network->n_ref = 1;
assert_se(network->filename = strdup("hogehoge.network"));
- assert_se(config_parse_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
+ assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
assert_se(network->n_static_addresses == 1);
assert_se(network_verify(network) >= 0);
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
-Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
-Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(link_config, match_type)
+Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name)
+Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path)
+Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver)
+Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)