diff --git a/man/systemd.link.xml b/man/systemd.link.xml index afc0ad8c5e1..d0e9f8e507d 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -103,10 +103,10 @@ OriginalName= - The device name, as exposed by the udev property - "INTERFACE". May contain shell style globs. This can not be - used to match on names that have already been changed from - userspace. Caution is advised when matching on + A whitespace-separated list of shell-style globs matching + the device name, as exposed by the udev property + "INTERFACE". This can not be used to match on names that have + already been changed from userspace. Caution is advised when matching on kernel-assigned names, as they are known to be unstable between reboots. @@ -114,15 +114,16 @@ Path= - The persistent path, as exposed by the - udev property ID_PATH. May - contain shell style globs. + A whitespace-separated list of shell-style globs matching + the persistent path, as exposed by the udev property + ID_PATH. Driver= - The driver currently bound to the device, + A whitespace-separated list of shell-style globs matching + the driver currently bound to the device, as exposed by the udev property DRIVER of its parent device, or if that is not set, the driver as exposed by ethtool -i @@ -132,7 +133,8 @@ Type= - The device type, as exposed by the udev + A whitespace-separated list of shell-style globs matching + the device type, as exposed by the udev property DEVTYPE. diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 9b3a92d266e..069b605eda4 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -107,15 +107,16 @@ Path= - The persistent path, as exposed by the udev - property ID_PATH. May contain shell - style globs. + A whitespace-separated list of shell-style globs + matching the persistent path, as exposed by the udev + property ID_PATH. Driver= - The driver currently bound to the device, as + A whitespace-separated list of shell-style globs + matching the driver currently bound to the device, as exposed by the udev property DRIVER of its parent device, or if that is not set the driver as exposed by ethtool -i of the @@ -125,16 +126,17 @@ Type= - The device type, as exposed by the udev property + A whitespace-separated list of shell-style globs + matching the device type, as exposed by the udev property DEVTYPE. Name= - The device name, as exposed by the udev property - INTERFACE. May contain shell style - globs. + A whitespace-separated list of shell-style globs + matching the device name, as exposed by the udev property + INTERFACE. diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index e4a15d0b8a1..870858ccd79 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -83,10 +83,10 @@ int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8 } bool net_match_config(const struct ether_addr *match_mac, - const char *match_path, - const char *match_driver, - const char *match_type, - const char *match_name, + char * const *match_paths, + char * const *match_drivers, + char * const *match_types, + char * const *match_names, Condition *match_host, Condition *match_virt, Condition *match_kernel, @@ -97,6 +97,10 @@ bool net_match_config(const struct ether_addr *match_mac, const char *dev_driver, const char *dev_type, const char *dev_name) { + char * const *match_path; + char * const *match_driver; + char * const *match_type; + char * const *match_name; if (match_host && !condition_test(match_host)) return false; @@ -113,22 +117,50 @@ bool net_match_config(const struct ether_addr *match_mac, if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN))) return false; - if (match_path && (!dev_path || fnmatch(match_path, dev_path, 0))) - return false; + if (!strv_isempty(match_paths)) { + if (!dev_path) + return false; - if (match_driver) { - if (dev_parent_driver && !streq(match_driver, dev_parent_driver)) - return false; - else if (!streq_ptr(match_driver, dev_driver)) - return false; + STRV_FOREACH(match_path, match_paths) + if (fnmatch(*match_path, dev_path, 0) != 0) + return true; + + return false; } - if (match_type && !streq_ptr(match_type, dev_type)) - return false; - - if (match_name && (!dev_name || fnmatch(match_name, dev_name, 0))) + if (!strv_isempty(match_drivers)) { + if (!dev_driver) return false; + STRV_FOREACH(match_driver, match_drivers) + if (fnmatch(*match_driver, dev_driver, 0) != 0) + return true; + + return false; + } + + if (!strv_isempty(match_types)) { + if (!dev_type) + return false; + + STRV_FOREACH(match_type, match_types) + if (fnmatch(*match_type, dev_type, 0) != 0) + return true; + + return false; + } + + if (!strv_isempty(match_names)) { + if (!dev_name) + return false; + + STRV_FOREACH(match_name, match_names) + if (fnmatch(*match_name, dev_name, 0) != 0) + return true; + + return false; + } + return true; } @@ -212,6 +244,49 @@ int config_parse_ifname(const char *unit, return 0; } +int config_parse_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) { + + char ***sv = data; + const char *word, *state; + size_t l; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + FOREACH_WORD(word, l, rvalue, state) { + char *n; + + n = strndup(word, l); + if (!n) + return log_oom(); + + if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue); + free(n); + return 0; + } + + r = strv_consume(sv, n); + if (r < 0) + return log_oom(); + } + + return 0; +} + 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 c64db2e79d2..e51717e9196 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -29,10 +29,10 @@ #include "condition.h" bool net_match_config(const struct ether_addr *match_mac, - const char *match_path, - const char *match_driver, - const char *match_type, - const char *match_name, + char * const *match_path, + char * const *match_driver, + char * const *match_type, + char * const *match_name, Condition *match_host, Condition *match_virt, Condition *match_kernel, @@ -56,6 +56,10 @@ int config_parse_ifname(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); +int config_parse_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); + int config_parse_ifalias(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); diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c index f1b58b322f3..36b40d32b93 100644 --- a/src/network/networkd-network-bus.c +++ b/src/network/networkd-network-bus.c @@ -68,10 +68,10 @@ const sd_bus_vtable network_vtable[] = { SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchPath", "s", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchDriver", "s", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchType", "s", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchName", "s", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1731e042281..9f6e65f98e4 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -16,10 +16,10 @@ struct ConfigPerfItem; %includes %% Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac) -Match.Path, config_parse_string, 0, offsetof(Network, match_path) -Match.Driver, config_parse_string, 0, offsetof(Network, match_driver) -Match.Type, config_parse_string, 0, offsetof(Network, match_type) -Match.Name, config_parse_ifname, 0, offsetof(Network, match_name) +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.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 3ebd4d7d588..c90f730f108 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -196,10 +196,10 @@ void network_free(Network *network) { free(network->filename); free(network->match_mac); - free(network->match_path); - free(network->match_driver); - free(network->match_type); - free(network->match_name); + strv_free(network->match_path); + strv_free(network->match_driver); + strv_free(network->match_type); + strv_free(network->match_name); free(network->description); free(network->dhcp_vendor_class_identifier); diff --git a/src/network/networkd.h b/src/network/networkd.h index 691d6030202..fdd0684fca1 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -100,10 +100,10 @@ struct Network { char *name; struct ether_addr *match_mac; - char *match_path; - char *match_driver; - char *match_type; - char *match_name; + char **match_path; + char **match_driver; + char **match_type; + char **match_name; Condition *match_host; Condition *match_virt; diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 191ab68fa1e..b25e4b3344e 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -17,10 +17,10 @@ struct ConfigPerfItem; %includes %% Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac) -Match.OriginalName, config_parse_ifname, 0, offsetof(link_config, match_name) -Match.Path, config_parse_string, 0, offsetof(link_config, match_path) -Match.Driver, config_parse_string, 0, offsetof(link_config, match_driver) -Match.Type, config_parse_string, 0, offsetof(link_config, match_type) +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.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, match_virt) Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel) diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index 688f836144a..cb434d1aee6 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -52,10 +52,10 @@ struct link_config { char *filename; struct ether_addr *match_mac; - char *match_path; - char *match_driver; - char *match_type; - char *match_name; + char **match_path; + char **match_driver; + char **match_type; + char **match_name; Condition *match_host; Condition *match_virt; Condition *match_kernel;