net: support globbing and disjunction in Match logic

Match{Name,OrginalName,Type,Driver,Path} can now take a space-separated glob of matches.
This commit is contained in:
Tom Gundersen 2015-02-10 18:30:16 +01:00
parent ea6ec096db
commit 5256e00e8b
10 changed files with 143 additions and 60 deletions

View File

@ -103,10 +103,10 @@
<varlistentry>
<term><varname>OriginalName=</varname></term>
<listitem>
<para>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
<para>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.</para>
</listitem>
@ -114,15 +114,16 @@
<varlistentry>
<term><varname>Path=</varname></term>
<listitem>
<para>The persistent path, as exposed by the
udev property <literal>ID_PATH</literal>. May
contain shell style globs.</para>
<para>A whitespace-separated list of shell-style globs matching
the persistent path, as exposed by the udev property
<literal>ID_PATH</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Driver=</varname></term>
<listitem>
<para>The driver currently bound to the device,
<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>
of its parent device, or if that is not set, the
driver as exposed by <literal>ethtool -i</literal>
@ -132,7 +133,8 @@
<varlistentry>
<term><varname>Type=</varname></term>
<listitem>
<para>The device type, as exposed by the udev
<para>A whitespace-separated list of shell-style globs matching
the device type, as exposed by the udev
property <literal>DEVTYPE</literal>.</para>
</listitem>
</varlistentry>

View File

@ -107,15 +107,16 @@
<varlistentry>
<term><varname>Path=</varname></term>
<listitem>
<para>The persistent path, as exposed by the udev
property <literal>ID_PATH</literal>. May contain shell
style globs.</para>
<para>A whitespace-separated list of shell-style globs
matching the persistent path, as exposed by the udev
property <literal>ID_PATH</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Driver=</varname></term>
<listitem>
<para>The driver currently bound to the device, as
<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>
of its parent device, or if that is not set the driver
as exposed by <literal>ethtool -i</literal> of the
@ -125,16 +126,17 @@
<varlistentry>
<term><varname>Type=</varname></term>
<listitem>
<para>The device type, as exposed by the udev property
<para>A whitespace-separated list of shell-style globs
matching the device type, as exposed by the udev property
<literal>DEVTYPE</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Name=</varname></term>
<listitem>
<para>The device name, as exposed by the udev property
<literal>INTERFACE</literal>. May contain shell style
globs.</para>
<para>A whitespace-separated list of shell-style globs
matching the device name, as exposed by the udev property
<literal>INTERFACE</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -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,

View File

@ -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);

View File

@ -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
};

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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;