diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 162674f769..fb091b883c 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -172,6 +172,17 @@ for details. + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for + details. + + + Architecture= diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 4e5d47f585..b9647a2f7a 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -232,6 +232,16 @@ + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for details. + + + Architecture= diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 3466f3a3cf..f78beaa7dc 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -193,6 +193,17 @@ + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for + details. + + + Architecture= diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 005fdea73c..19a6db7f65 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -923,6 +923,7 @@ ConditionVirtualization= ConditionHost= ConditionKernelCommandLine= + ConditionKernelVersion= ConditionSecurity= ConditionCapability= ConditionACPower= @@ -1050,6 +1051,17 @@ the exact assignment is looked for with right and left hand side matching. + ConditionKernelVersion= may be used to check whether the kernel version (as reported + by uname -r) matches a certain expression (or if prefixed with the exclamation mark does not + match it). The argument must be a single string. If the string starts with one of <, + <=, =, >=, > a relative + version comparison is done, otherwise the specified string is matched with shell-style globs. + + Note that using the kernel version string is an unreliable way to determine which features are supported + by a kernel, because of the widespread practice of backporting drivers, features, and fixes from newer upstream + kernels into older versions provided by distributions. Hence, this check is inherently unportable and should + not be used for units which may be used on different distributions. + ConditionSecurity= may be used to check whether the given security module is enabled on the system. Currently, the recognized values are @@ -1201,6 +1213,7 @@ AssertVirtualization= AssertHost= AssertKernelCommandLine= + AssertKernelVersion= AssertSecurity= AssertCapability= AssertACPower= diff --git a/src/basic/util.c b/src/basic/util.c index 5dd3c3014f..2a39ff2b53 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -553,3 +553,65 @@ int version(void) { SYSTEMD_FEATURES); return 0; } + +/* This is a direct translation of str_verscmp from boot.c */ +static bool is_digit(int c) { + return c >= '0' && c <= '9'; +} + +static int c_order(int c) { + if (c == 0 || is_digit(c)) + return 0; + + if ((c >= 'a') && (c <= 'z')) + return c; + + return c + 0x10000; +} + +int str_verscmp(const char *s1, const char *s2) { + const char *os1, *os2; + + assert(s1); + assert(s2); + + os1 = s1; + os2 = s2; + + while (*s1 || *s2) { + int first; + + while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { + int order; + + order = c_order(*s1) - c_order(*s2); + if (order != 0) + return order; + s1++; + s2++; + } + + while (*s1 == '0') + s1++; + while (*s2 == '0') + s2++; + + first = 0; + while (is_digit(*s1) && is_digit(*s2)) { + if (first == 0) + first = *s1 - *s2; + s1++; + s2++; + } + + if (is_digit(*s1)) + return 1; + if (is_digit(*s2)) + return -1; + + if (first != 0) + return first; + } + + return strcmp(os1, os2); +} diff --git a/src/basic/util.h b/src/basic/util.h index 8cd78171bc..20181ab917 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -189,3 +189,5 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max); int update_reboot_parameter_and_warn(const char *param); int version(void); + +int str_verscmp(const char *s1, const char *s2); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 5604312bc5..549c7eb4d6 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -241,6 +241,7 @@ Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_F Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) +Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) @@ -263,6 +264,7 @@ Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_F Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) +Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index e48b7d22dd..c20e9fca35 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -116,7 +116,8 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_names, Condition *match_host, Condition *match_virt, - Condition *match_kernel, + Condition *match_kernel_cmdline, + Condition *match_kernel_version, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, @@ -131,7 +132,10 @@ bool net_match_config(const struct ether_addr *match_mac, if (match_virt && condition_test(match_virt) <= 0) return false; - if (match_kernel && condition_test(match_kernel) <= 0) + if (match_kernel_cmdline && condition_test(match_kernel_cmdline) <= 0) + return false; + + if (match_kernel_version && condition_test(match_kernel_version) <= 0) return false; if (match_arch && condition_test(match_arch) <= 0) diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index a54adac602..4e69f1a598 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -37,7 +37,8 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_name, Condition *match_host, Condition *match_virt, - Condition *match_kernel, + Condition *match_kernel_cmdline, + Condition *match_kernel_version, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 3aeba06ee0..03b8661957 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -33,7 +33,8 @@ struct ConfigPerfItem; %% Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(NetDev, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, match_arch) NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 7afe30f7fb..7cf110672f 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -149,7 +149,8 @@ static void netdev_free(NetDev *netdev) { condition_free_list(netdev->match_host); condition_free_list(netdev->match_virt); - condition_free_list(netdev->match_kernel); + condition_free_list(netdev->match_kernel_cmdline); + condition_free_list(netdev->match_kernel_version); condition_free_list(netdev->match_arch); if (NETDEV_VTABLE(netdev) && @@ -642,7 +643,8 @@ static int netdev_load_one(Manager *manager, const char *filename) { /* skip out early if configuration does not match the environment */ if (net_match_config(NULL, NULL, NULL, NULL, NULL, netdev_raw->match_host, netdev_raw->match_virt, - netdev_raw->match_kernel, netdev_raw->match_arch, + netdev_raw->match_kernel_cmdline, netdev_raw->match_kernel_version, + netdev_raw->match_arch, NULL, NULL, NULL, NULL, NULL, NULL) <= 0) return 0; diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 24915b2b04..507b86a078 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -93,7 +93,8 @@ typedef struct NetDev { Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; NetDevState state; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 57a96aff94..cb0c01fbe7 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -27,7 +27,8 @@ Match.Type, config_parse_strv, 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) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 8e37a0a229..b037fc67e3 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -431,7 +431,8 @@ void network_free(Network *network) { condition_free_list(network->match_host); condition_free_list(network->match_virt); - condition_free_list(network->match_kernel); + condition_free_list(network->match_kernel_cmdline); + condition_free_list(network->match_kernel_version); condition_free_list(network->match_arch); free(network->dhcp_server_timezone); @@ -485,8 +486,8 @@ int network_get(Manager *manager, struct udev_device *device, if (net_match_config(network->match_mac, network->match_path, network->match_driver, network->match_type, network->match_name, network->match_host, - network->match_virt, network->match_kernel, - network->match_arch, + network->match_virt, network->match_kernel_cmdline, + network->match_kernel_version, network->match_arch, address, path, parent_driver, driver, devtype, ifname)) { if (network->match_name && device) { diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 49c62654b6..702aa7692a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -112,7 +112,8 @@ struct Network { Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; char *description; diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index e97b5cdb79..4f255f620b 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -203,67 +203,8 @@ int boot_loader_read_conf(const char *path, BootConfig *config) { return 0; } -/* This is a direct translation of str_verscmp from boot.c */ -static bool is_digit(int c) { - return c >= '0' && c <= '9'; -} - -static int c_order(int c) { - if (c == '\0') - return 0; - if (is_digit(c)) - return 0; - else if ((c >= 'a') && (c <= 'z')) - return c; - else - return c + 0x10000; -} - -static int str_verscmp(const char *s1, const char *s2) { - const char *os1 = s1; - const char *os2 = s2; - - while (*s1 || *s2) { - int first; - - while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { - int order; - - order = c_order(*s1) - c_order(*s2); - if (order) - return order; - s1++; - s2++; - } - - while (*s1 == '0') - s1++; - while (*s2 == '0') - s2++; - - first = 0; - while (is_digit(*s1) && is_digit(*s2)) { - if (first == 0) - first = *s1 - *s2; - s1++; - s2++; - } - - if (is_digit(*s1)) - return 1; - if (is_digit(*s2)) - return -1; - - if (first != 0) - return first; - } - - return strcmp(os1, os2); -} - static int boot_entry_compare(const void *a, const void *b) { - const BootEntry *aa = a; - const BootEntry *bb = b; + const BootEntry *aa = a, *bb = b; return str_verscmp(aa->filename, bb->filename); } diff --git a/src/shared/condition.c b/src/shared/condition.c index d4bbaf3c65..7a825c3973 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -143,6 +144,70 @@ static int condition_test_kernel_command_line(Condition *c) { return false; } +static int condition_test_kernel_version(Condition *c) { + enum { + /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest + * should be listed first. */ + LOWER_OR_EQUAL, + GREATER_OR_EQUAL, + LOWER, + GREATER, + EQUAL, + _ORDER_MAX, + }; + + static const char *const prefix[_ORDER_MAX] = { + [LOWER_OR_EQUAL] = "<=", + [GREATER_OR_EQUAL] = ">=", + [LOWER] = "<", + [GREATER] = ">", + [EQUAL] = "=", + }; + const char *p = NULL; + struct utsname u; + size_t i; + int k; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_KERNEL_VERSION); + + assert_se(uname(&u) >= 0); + + for (i = 0; i < _ORDER_MAX; i++) { + p = startswith(c->parameter, prefix[i]); + if (p) + break; + } + + /* No prefix? Then treat as glob string */ + if (!p) + return fnmatch(skip_leading_chars(c->parameter, NULL), u.release, 0) == 0; + + k = str_verscmp(u.release, skip_leading_chars(p, NULL)); + + switch (i) { + + case LOWER: + return k < 0; + + case LOWER_OR_EQUAL: + return k <= 0; + + case EQUAL: + return k == 0; + + case GREATER_OR_EQUAL: + return k >= 0; + + case GREATER: + return k > 0; + + default: + assert_not_reached("Can't compare"); + } +} + static int condition_test_user(Condition *c) { uid_t id; int r; @@ -552,6 +617,7 @@ int condition_test(Condition *c) { [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line, + [CONDITION_KERNEL_VERSION] = condition_test_kernel_version, [CONDITION_VIRTUALIZATION] = condition_test_virtualization, [CONDITION_SECURITY] = condition_test_security, [CONDITION_CAPABILITY] = condition_test_capability, @@ -612,6 +678,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", [CONDITION_HOST] = "ConditionHost", [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "ConditionKernelVersion", [CONDITION_SECURITY] = "ConditionSecurity", [CONDITION_CAPABILITY] = "ConditionCapability", [CONDITION_AC_POWER] = "ConditionACPower", @@ -639,6 +706,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_VIRTUALIZATION] = "AssertVirtualization", [CONDITION_HOST] = "AssertHost", [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "AssertKernelVersion", [CONDITION_SECURITY] = "AssertSecurity", [CONDITION_CAPABILITY] = "AssertCapability", [CONDITION_AC_POWER] = "AssertACPower", diff --git a/src/shared/condition.h b/src/shared/condition.h index 715866be70..98af2daaee 100644 --- a/src/shared/condition.h +++ b/src/shared/condition.h @@ -31,6 +31,7 @@ typedef enum ConditionType { CONDITION_VIRTUALIZATION, CONDITION_HOST, CONDITION_KERNEL_COMMAND_LINE, + CONDITION_KERNEL_VERSION, CONDITION_SECURITY, CONDITION_CAPABILITY, CONDITION_AC_POWER, diff --git a/src/test/test-condition.c b/src/test/test-condition.c index bf455aac89..8323a66ad3 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -20,6 +20,7 @@ #include #include +#include #include #include "sd-id128.h" @@ -38,10 +39,11 @@ #include "selinux-util.h" #include "set.h" #include "smack-util.h" +#include "string-util.h" #include "strv.h" -#include "virt.h" -#include "util.h" #include "user-util.h" +#include "util.h" +#include "virt.h" static void test_condition_test_path(void) { Condition *condition; @@ -298,6 +300,126 @@ static void test_condition_test_kernel_command_line(void) { condition_free(condition); } +static void test_condition_test_kernel_version(void) { + Condition *condition; + struct utsname u; + const char *v; + + condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + assert_se(uname(&u) >= 0); + + condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + strshorten(u.release, 4); + strcpy(strchr(u.release, 0), "*"); + + condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + /* 0.1.2 would be a very very very old kernel */ + condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + /* 4711.8.15 is a very very very future kernel */ + condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + assert_se(uname(&u) >= 0); + + v = strjoina(">=", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + v = strjoina("= ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + v = strjoina("<=", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + v = strjoina("> ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); + + v = strjoina("< ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(!condition_test(condition)); + condition_free(condition); +} + static void test_condition_test_null(void) { Condition *condition; @@ -556,6 +678,7 @@ int main(int argc, char *argv[]) { test_condition_test_host(); test_condition_test_architecture(); test_condition_test_kernel_command_line(); + test_condition_test_kernel_version(); test_condition_test_null(); test_condition_test_security(); test_condition_test_virtualization(); diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 85f0a0625b..5cb126d870 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -26,7 +26,8 @@ Match.Driver, config_parse_strv, 0, 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) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, match_arch) Link.Description, config_parse_string, 0, offsetof(link_config, description) Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 92d41a6e95..a4368f088d 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -77,7 +77,8 @@ static void link_config_free(link_config *link) { free(link->match_name); free(link->match_host); free(link->match_virt); - free(link->match_kernel); + free(link->match_kernel_cmdline); + free(link->match_kernel_version); free(link->match_arch); free(link->description); @@ -248,7 +249,8 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, if (net_match_config(link->match_mac, link->match_path, link->match_driver, link->match_type, link->match_name, link->match_host, - link->match_virt, link->match_kernel, link->match_arch, + link->match_virt, link->match_kernel_cmdline, + link->match_kernel_version, link->match_arch, attr_value ? ether_aton(attr_value) : NULL, udev_device_get_property_value(device, "ID_PATH"), udev_device_get_driver(udev_device_get_parent(device)), diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index a413251bd0..dabc3eff8f 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -58,7 +58,8 @@ struct link_config { char **match_name; Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; char *description;