From: Tom Gundersen Date: Tue, 10 Feb 2015 17:30:16 +0000 (+0100) Subject: net: support globbing and disjunction in Match logic X-Git-Tag: v219~86 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=5256e00e8b9015dd1a976d647fc71dc7efbd8cf8;hp=ea6ec096db5f9f3562b9bbf438da7fe21411c74d net: support globbing and disjunction in Match logic Match{Name,OrginalName,Type,Driver,Path} can now take a space-separated glob of matches. --- diff --git a/man/systemd.link.xml b/man/systemd.link.xml index afc0ad8c5..d0e9f8e50 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 9b3a92d26..069b605ed 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 e4a15d0b8..870858ccd 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))) + if (!strv_isempty(match_paths)) { + if (!dev_path) + return false; + + STRV_FOREACH(match_path, match_paths) + if (fnmatch(*match_path, dev_path, 0) != 0) + return true; + 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)) + 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 (match_type && !streq_ptr(match_type, dev_type)) + 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 (match_name && (!dev_name || fnmatch(match_name, dev_name, 0))) + 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 c64db2e79..e51717e91 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 f1b58b322..36b40d32b 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 1731e0422..9f6e65f98 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 3ebd4d7d5..c90f730f1 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 691d60302..fdd0684fc 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 191ab68fa..b25e4b334 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 688f83614..cb434d1ae 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;