diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-07-01 20:33:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-01 20:33:24 +0200 |
commit | 0330cb57ab08d37c7c94b4b4871b613b4cd08a0c (patch) | |
tree | d5dccf64397bba4bf480d9891d7f89404c661006 | |
parent | 9c69cd7ec02f9cca3fdb313beb992ae8ea16e8e4 (diff) | |
parent | 6b9518a0e84b01b1cfa07d0f3b18e7764ac25085 (diff) | |
download | systemd-0330cb57ab08d37c7c94b4b4871b613b4cd08a0c.tar.gz |
Merge pull request #12888 from yuwata/network-udev-property-support
network,udev: add Property= setting in [Match] section
-rw-r--r-- | man/systemd.link.xml | 17 | ||||
-rw-r--r-- | man/systemd.network.xml | 17 | ||||
-rw-r--r-- | src/libsystemd-network/network-internal.c | 239 | ||||
-rw-r--r-- | src/libsystemd-network/network-internal.h | 9 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 9 | ||||
-rw-r--r-- | src/network/networkd-network.c | 20 | ||||
-rw-r--r-- | src/network/networkd-network.h | 1 | ||||
-rw-r--r-- | src/network/test-networkd-conf.c | 25 | ||||
-rw-r--r-- | src/udev/net/link-config-gperf.gperf | 9 | ||||
-rw-r--r-- | src/udev/net/link-config.c | 30 | ||||
-rw-r--r-- | src/udev/net/link-config.h | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-link-parser/directives.link | 1 | ||||
-rw-r--r-- | test/fuzz/fuzz-network-parser/directives.network | 1 | ||||
-rw-r--r-- | test/test-network/conf/13-not-match-udev-property.network | 6 | ||||
-rw-r--r-- | test/test-network/conf/14-match-udev-property.network | 7 | ||||
-rwxr-xr-x | test/test-network/systemd-networkd-tests.py | 11 |
16 files changed, 325 insertions, 78 deletions
diff --git a/man/systemd.link.xml b/man/systemd.link.xml index b1be32955e..7ea9a71107 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -103,7 +103,7 @@ <term><varname>Driver=</varname></term> <listitem> <para>A whitespace-separated list of shell-style globs matching the driver currently bound to the - device, as exposed by the udev property <varname>DRIVER</varname> of its parent device, or if that + device, as exposed by the udev property <varname>ID_NET_DRIVER</varname> of its parent device, or if that is not set, the driver as exposed by <command>ethtool -i</command> of the device itself.</para> </listitem> </varlistentry> @@ -116,6 +116,21 @@ </listitem> </varlistentry> <varlistentry> + <term><varname>Property=</varname></term> + <listitem> + <para>A whitespace-separated list of udev property name with its value after a equal + (<literal>=</literal>). If multiple properties are specified, the test results are ANDed. + If the list is prefixed with a "!", the test is inverted. If a value contains white + spaces, then please quote whole key and value pair. If a value contains quotation, then + please escape the quotation with <literal>\</literal>.</para> + + <para>Example: if a .link file has the following: + <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting> + then, the .link file matches only when an interface has all the above three properties. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><varname>Host=</varname></term> <listitem> <para>Matches against the hostname or machine ID of the host. See <varname>ConditionHost=</varname> in diff --git a/man/systemd.network.xml b/man/systemd.network.xml index bad673b44e..d32b60a2c9 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -113,7 +113,7 @@ <listitem> <para>A whitespace-separated list of shell-style globs matching the driver currently bound to the device, as - exposed by the udev property <literal>DRIVER</literal> + exposed by the udev property <literal>ID_NET_DRIVER</literal> of its parent device, or if that is not set the driver as exposed by <literal>ethtool -i</literal> of the device itself. If the list is prefixed with a "!", the @@ -139,6 +139,21 @@ </listitem> </varlistentry> <varlistentry> + <term><varname>Property=</varname></term> + <listitem> + <para>A whitespace-separated list of udev property name with its value after a equal + (<literal>=</literal>). If multiple properties are specified, the test results are ANDed. + If the list is prefixed with a "!", the test is inverted. If a value contains white + spaces, then please quote whole key and value pair. If a value contains quotation, then + please escape the quotation with <literal>\</literal>.</para> + + <para>Example: if a .network file has the following: + <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting> + then, the .network file matches only when an interface has all the above three properties. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><varname>Host=</varname></term> <listitem> <para>Matches against the hostname or machine ID of the host. See diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index 9a1b2fba89..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" @@ -73,26 +74,66 @@ int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_ 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; + + if (!invert) + has_positive_rule = true; + + if (string && fnmatch(q, string, 0) == 0) { + if (invert) + return false; + else + match = true; + } + } + + 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++; - 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]; + v = device && + sd_device_get_property_value(device, key, &dev_val) >= 0 && + fnmatch(val, dev_val, 0) == 0; - return !string || !strv_fnmatch(patterns, string, 0); + if (invert ? v : !v) + return false; } - return string && strv_fnmatch(raw_patterns, string, 0); + return true; } bool net_match_config(Set *match_mac, @@ -100,12 +141,25 @@ bool net_match_config(Set *match_mac, 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_path, - const char *dev_driver, - const char *dev_type, const char *dev_name) { + const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str; + + if (device) { + (void) sd_device_get_property_value(device, "ID_PATH", &dev_path); + (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver); + (void) sd_device_get_devtype(device, &dev_type); + + if (!dev_name) + (void) sd_device_get_sysname(device, &dev_name); + if (!dev_mac && + sd_device_get_sysattr_value(device, "address", &mac_str) >= 0) + dev_mac = ether_aton(mac_str); + } + if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac))) return false; @@ -121,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; } @@ -164,7 +221,7 @@ int config_parse_net_condition(const char *unit, return 0; } -int config_parse_ifnames( +int config_parse_match_strv( const char *unit, const char *filename, unsigned line, @@ -176,7 +233,9 @@ int config_parse_ifnames( void *data, void *userdata) { + const char *p = rvalue; char ***sv = data; + bool invert; int r; assert(filename); @@ -184,30 +243,154 @@ int config_parse_ifnames( 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_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, diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index ebfb1c3c75..7059c8ae45 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -19,16 +19,17 @@ 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_path, - const char *dev_driver, - const char *dev_type, const char *dev_name); 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_match_property); CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 2986ff1123..8d0a596c87 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -22,10 +22,11 @@ struct ConfigPerfItem; %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.Property, config_parse_match_property, 0, offsetof(Network, match_property) 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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 0741dfe646..8b8311058c 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -157,7 +157,8 @@ int network_verify(Network *network) { if (set_isempty(network->match_mac) && strv_isempty(network->match_path) && strv_isempty(network->match_driver) && strv_isempty(network->match_type) && - strv_isempty(network->match_name) && !network->conditions) + strv_isempty(network->match_name) && strv_isempty(network->match_property) && + !network->conditions) log_warning("%s: No valid settings found in the [Match] section. " "The file will match all interfaces. " "If that is intended, please add Name=* in the [Match] section.", @@ -507,6 +508,7 @@ static Network *network_free(Network *network) { strv_free(network->match_driver); strv_free(network->match_type); strv_free(network->match_name); + strv_free(network->match_property); condition_free_list(network->conditions); free(network->description); @@ -607,26 +609,16 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) { int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *address, Network **ret) { - const char *path = NULL, *driver = NULL, *devtype = NULL; Network *network; Iterator i; assert(manager); assert(ret); - if (device) { - (void) sd_device_get_property_value(device, "ID_PATH", &path); - - (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver); - - (void) sd_device_get_devtype(device, &devtype); - } - ORDERED_HASHMAP_FOREACH(network, manager->networks, i) - if (net_match_config(network->match_mac, network->match_path, - network->match_driver, network->match_type, - network->match_name, - address, path, driver, devtype, ifname)) { + if (net_match_config(network->match_mac, network->match_path, network->match_driver, + network->match_type, network->match_name, network->match_property, + device, address, ifname)) { if (network->match_name && device) { const char *attr; uint8_t name_assign_type = NET_NAME_UNKNOWN; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 7b92a54426..2b7cca8bae 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -104,6 +104,7 @@ struct Network { char **match_driver; char **match_type; char **match_name; + char **match_property; LIST_HEAD(Condition, conditions); char *description; diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index dfb41f801b..07ca127654 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -174,7 +174,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign 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); @@ -215,6 +215,27 @@ static void test_config_parse_address(void) { test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0); } +static void test_config_parse_match_ifnames(void) { + _cleanup_strv_free_ char **names = NULL; + + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0); + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0); + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "aaa bbb ccc", &names, NULL) == 0); + + strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc")); +} + +static void test_config_parse_match_strv(void) { + _cleanup_strv_free_ char **names = NULL; + + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0); + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0); + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, + "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"", &names, NULL) == 0); + + strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "KEY=val", "KEY2=val with space", "KEY3=val with \"quotation\"")); +} + int main(int argc, char **argv) { log_parse_environment(); log_open(); @@ -223,6 +244,8 @@ int main(int argc, char **argv) { test_config_parse_duid_rawdata(); test_config_parse_hwaddr(); test_config_parse_address(); + test_config_parse_match_ifnames(); + test_config_parse_match_strv(); return 0; } diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 9698211d1d..a3d7dec88c 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -20,10 +20,11 @@ struct ConfigPerfItem; %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.Property, config_parse_match_property, 0, offsetof(link_config, match_property) 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) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 611add9ae0..9989e6ab65 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -51,6 +51,7 @@ static void link_config_free(link_config *link) { strv_free(link->match_driver); strv_free(link->match_type); strv_free(link->match_name); + strv_free(link->match_property); condition_free_list(link->conditions); free(link->description); @@ -161,7 +162,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) { if (set_isempty(link->match_mac) && strv_isempty(link->match_path) && strv_isempty(link->match_driver) && strv_isempty(link->match_type) && - strv_isempty(link->match_name) && !link->conditions) + strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions) log_warning("%s: No valid settings found in the [Match] section. " "The file will match all interfaces. " "If that is intended, please add OriginalName=* in the [Match] section.", @@ -240,42 +241,29 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) assert(ret); LIST_FOREACH(links, link, ctx->links) { - const char *address = NULL, *id_path = NULL, *id_net_driver = NULL, *devtype = NULL, *sysname = NULL; - - (void) sd_device_get_sysattr_value(device, "address", &address); - (void) sd_device_get_property_value(device, "ID_PATH", &id_path); - (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &id_net_driver); - (void) sd_device_get_devtype(device, &devtype); - (void) sd_device_get_sysname(device, &sysname); - if (net_match_config(link->match_mac, link->match_path, link->match_driver, - link->match_type, link->match_name, - address ? ether_aton(address) : NULL, - id_path, - id_net_driver, - devtype, - sysname)) { + link->match_type, link->match_name, link->match_property, + device, NULL, NULL)) { if (link->match_name) { unsigned name_assign_type = NET_NAME_UNKNOWN; (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type); if (name_assign_type == NET_NAME_ENUM && !strv_contains(link->match_name, "*")) { - log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'", - link->filename, sysname); + log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name", + link->filename); *ret = link; return 0; } else if (name_assign_type == NET_NAME_RENAMED) { - log_warning("Config file %s matches device based on renamed interface name '%s', ignoring", - link->filename, sysname); + log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring", + link->filename); continue; } } - log_debug("Config file %s applies to device %s", - link->filename, sysname); + log_device_debug(device, "Config file %s is applied", link->filename); *ret = link; return 0; diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index a45a0e709a..cd99cd54d4 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -40,6 +40,7 @@ struct link_config { char **match_driver; char **match_type; char **match_name; + char **match_property; LIST_HEAD(Condition, conditions); char *description; diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link index 5925e5ad12..61155063a8 100644 --- a/test/fuzz/fuzz-link-parser/directives.link +++ b/test/fuzz/fuzz-link-parser/directives.link @@ -4,6 +4,7 @@ OriginalName= Path= Driver= Type= +Property= Host= Virtualization= KernelCommandLine= diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 496c52336c..26dd83d8da 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -20,6 +20,7 @@ Driver= Architecture= Path= Name= +Property= Virtualization= KernelCommandLine= Host= diff --git a/test/test-network/conf/13-not-match-udev-property.network b/test/test-network/conf/13-not-match-udev-property.network new file mode 100644 index 0000000000..f0a530e9db --- /dev/null +++ b/test/test-network/conf/13-not-match-udev-property.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 +Property=INTERFACE=hoge + +[Network] +IPv6AcceptRA=false diff --git a/test/test-network/conf/14-match-udev-property.network b/test/test-network/conf/14-match-udev-property.network new file mode 100644 index 0000000000..b632af166a --- /dev/null +++ b/test/test-network/conf/14-match-udev-property.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 +Property=INTERFACE=dummy98 + +[Network] +IPv6AcceptRA=false +Address=10.1.2.3/16 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 9c274c128d..75863c3910 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -463,6 +463,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '11-dummy.netdev', '11-dummy.network', '12-dummy.netdev', + '13-not-match-udev-property.network', + '14-match-udev-property.network', '15-name-conflict-test.netdev', '21-macvlan.netdev', '21-macvtap.netdev', @@ -578,6 +580,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, '00:50:56:c0:00:28') + def test_match_udev_property(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network') + start_networkd() + wait_online(['dummy98:routable']) + + output = check_output('networkctl status dummy98') + print(output) + self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property') + def test_wait_online_any(self): copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network') start_networkd() |