summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-06-23 01:44:13 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-07-01 01:24:42 +0900
commit44005bfb4eaae840e481e7a0d0b74ac9ee418302 (patch)
tree6fa79fee336f4c0b45800fc84c487d0d670aea56 /src/libsystemd-network
parentb38de0e9cc1dfd60a89cf9ec998ed94e71610d50 (diff)
downloadsystemd-44005bfb4eaae840e481e7a0d0b74ac9ee418302.tar.gz
network,udev: add Property= setting in [Match] section
Closes #5665.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/network-internal.c97
-rw-r--r--src/libsystemd-network/network-internal.h2
2 files changed, 99 insertions, 0 deletions
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 1f02a1e984..1f2e5c7e65 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -12,6 +12,7 @@
#include "conf-parser.h"
#include "device-util.h"
#include "dhcp-lease-internal.h"
+#include "env-util.h"
#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
@@ -101,11 +102,46 @@ static bool net_condition_test_strv(char * const *patterns, const char *string)
return has_positive_rule ? match : true;
}
+static int net_condition_test_property(char * const *match_property, sd_device *device) {
+ char * const *p;
+
+ if (strv_isempty(match_property))
+ return true;
+
+ STRV_FOREACH(p, match_property) {
+ _cleanup_free_ char *key = NULL;
+ const char *val, *dev_val;
+ bool invert, v;
+
+ invert = **p == '!';
+
+ val = strchr(*p + invert, '=');
+ if (!val)
+ return -EINVAL;
+
+ key = strndup(*p + invert, val - *p - invert);
+ if (!key)
+ return -ENOMEM;
+
+ val++;
+
+ v = device &&
+ sd_device_get_property_value(device, key, &dev_val) >= 0 &&
+ fnmatch(val, dev_val, 0) == 0;
+
+ if (invert ? v : !v)
+ return false;
+ }
+
+ return true;
+}
+
bool net_match_config(Set *match_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_types,
char * const *match_names,
+ char * const *match_property,
sd_device *device,
const struct ether_addr *dev_mac,
const char *dev_name) {
@@ -139,6 +175,9 @@ bool net_match_config(Set *match_mac,
if (!net_condition_test_strv(match_names, dev_name))
return false;
+ if (!net_condition_test_property(match_property, device))
+ return false;
+
return true;
}
@@ -296,6 +335,64 @@ int config_parse_match_ifnames(
}
}
+int config_parse_match_property(
+ 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, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!env_assignment_is_valid(word)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid property or value, ignoring assignment: %s", word);
+ continue;
+ }
+
+ 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_ifalias(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index f6e69078fa..7059c8ae45 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -19,6 +19,7 @@ bool net_match_config(Set *match_mac,
char * const *match_driver,
char * const *match_type,
char * const *match_name,
+ char * const *match_property,
sd_device *device,
const struct ether_addr *dev_mac,
const char *dev_name);
@@ -28,6 +29,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);