]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core,udev,networkd: add ConditionKernelVersion=
authorLennart Poettering <lennart@poettering.net>
Wed, 13 Dec 2017 19:34:13 +0000 (20:34 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 26 Dec 2017 16:39:44 +0000 (17:39 +0100)
This adds a simple condition/assert/match to the service manager, to
udev's .link handling and to networkd, for matching the kernel version
string.

In this version we only do fnmatch() based globbing, but we might want
to extend that to version comparisons later on, if we like, by slightly
extending the syntax with ">=", "<=", ">", "<" and "==" expressions.

19 files changed:
man/systemd.link.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.unit.xml
src/core/load-fragment-gperf.gperf.m4
src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/shared/condition.c
src/shared/condition.h
src/test/test-condition.c
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h

index 162674f769895c3939e982da8267731dcda08a19..fb091b883ce4636aafb0df7ed406e772a97c9910 100644 (file)
           for details.</para>
         </listitem>
       </varlistentry>
+        <varlistentry>
+          <term><varname>KernelVersion=</varname></term>
+          <listitem>
+            <para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
+            expression (or if prefixed with the exclamation mark does not match it). See
+            <literal>ConditionKernelVersion=</literal> in
+            <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+            details.
+            </para>
+          </listitem>
+        </varlistentry>
       <varlistentry>
         <term><varname>Architecture=</varname></term>
         <listitem>
index 4e5d47f585a9dbd8a3a6d7eb600364ba045abe63..b9647a2f7a54e21cff964e2198556af9931fad0e 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>KernelVersion=</varname></term>
+        <listitem>
+          <para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
+          expression (or if prefixed with the exclamation mark does not match it). See
+          <literal>ConditionKernelVersion=</literal> in
+          <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details.
+          </para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>Architecture=</varname></term>
         <listitem>
index 3466f3a3cf71af3da6ff6d26c0ac046beb8f7fa4..f78beaa7dc72b7694ab85c23c75b4775dab3ea01 100644 (file)
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>KernelVersion=</varname></term>
+          <listitem>
+            <para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
+            expression (or if prefixed with the exclamation mark does not match it). See
+            <literal>ConditionKernelVersion=</literal> in
+            <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+            details.
+            </para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Architecture=</varname></term>
           <listitem>
index 005fdea73cdbda292b6ead11c789dffebc280a1e..0d35d619e015c60045c663a1f00dc4c52b03e186 100644 (file)
         <term><varname>ConditionVirtualization=</varname></term>
         <term><varname>ConditionHost=</varname></term>
         <term><varname>ConditionKernelCommandLine=</varname></term>
+        <term><varname>ConditionKernelVersion=</varname></term>
         <term><varname>ConditionSecurity=</varname></term>
         <term><varname>ConditionCapability=</varname></term>
         <term><varname>ConditionACPower=</varname></term>
         the exact assignment is looked for with right and left hand
         side matching.</para>
 
+        <para><varname>ConditionKernelVersion=</varname> may be used to check whether the kernel version (as reported
+        by <command>uname -r</command>) matches a certain expression (or if prefixed with the exclamation mark does not
+        match it). The argument must be a single string, optionally containing shell-style globs.</para>
+
         <para><varname>ConditionSecurity=</varname> may be used to
         check whether the given security module is enabled on the
         system. Currently, the recognized values are
         <term><varname>AssertVirtualization=</varname></term>
         <term><varname>AssertHost=</varname></term>
         <term><varname>AssertKernelCommandLine=</varname></term>
+        <term><varname>AssertKernelVersion=</varname></term>
         <term><varname>AssertSecurity=</varname></term>
         <term><varname>AssertCapability=</varname></term>
         <term><varname>AssertACPower=</varname></term>
index 5604312bc5e41cea5c8176049140051a0c787169..549c7eb4d6f9aa8e271def3a0b956a3d518b50b2 100644 (file)
@@ -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)
index e48b7d22ddcec404cb716784c380f982455b657f..c20e9fca35393960ceb24049548cf46f0e67d4cf 100644 (file)
@@ -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)
index a54adac602aeaa2505baa85093c52c1f105e92c7..4e69f1a59882f707b40d74d806e936ee51325ef7 100644 (file)
@@ -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,
index 3aeba06ee01826aec0ff02831f1efb6e14d09162..03b86619574339af75be0e2c556ec5b7ca6da341 100644 (file)
@@ -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)
index 7afe30f7fbae15deabdd3f49944d88c4ba225779..7cf110672f261b52ca9b4096616d39284fc58d7c 100644 (file)
@@ -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;
 
index 24915b2b04b3ab68cc0cfab5d81beb7290756fd2..507b86a078f96c99a40856bef218c00eae48f855 100644 (file)
@@ -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;
index 57a96aff941e398ae31117b7f759d4a8c1847def..cb0c01fbe740f0eb67d0c52169c58efc1014693c 100644 (file)
@@ -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)
index 8e37a0a229f2da2c124f622bcb6db9a141f9293f..b037fc67e3706ddee8b962f2ce351a57c1aad997 100644 (file)
@@ -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) {
index 49c62654b6b72a1ffabf2ec379c02924ccf9eae2..702aa7692a4ae3b0facef503818cc5867d00a8ff 100644 (file)
@@ -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;
index d4bbaf3c65d22e58936a377e9227b5690899e7ac..887c9a758864d9486f7cc9b268c4e5417548214a 100644 (file)
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -143,6 +144,18 @@ static int condition_test_kernel_command_line(Condition *c) {
         return false;
 }
 
+static int condition_test_kernel_version(Condition *c) {
+        struct utsname u;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_KERNEL_VERSION);
+
+        assert_se(uname(&u) >= 0);
+
+        return fnmatch(c->parameter, u.release, 0) == 0;
+}
+
 static int condition_test_user(Condition *c) {
         uid_t id;
         int r;
@@ -552,6 +565,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 +626,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 +654,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",
index 715866be704d3f949614308cd8e73698d008a727..98af2daaeeee6ba37d6556decfd87b23d2aaba6f 100644 (file)
@@ -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,
index bf455aac8911dfc95b45730f72440053ecfa026a..8fb2ad5d18c29640e5774540790169136fe9abac 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <unistd.h>
 
 #include "sd-id128.h"
 #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,41 @@ 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;
+
+        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);
+}
+
 static void test_condition_test_null(void) {
         Condition *condition;
 
@@ -556,6 +593,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();
index 85f0a0625b296621114b44f45c211846b2775b73..5cb126d870b7dfeff78f9accbb2061fa2ebd72d1 100644 (file)
@@ -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)
index 92d41a6e95bfcf7dba646d4c6d26a057aabcb38d..a4368f088d172cff69631e510cd4d5ff218f0397 100644 (file)
@@ -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)),
index a413251bd068bee568c2230d19344d543b0bc1e9..dabc3eff8f91f1481dc850ccc260ea94ad2b85d2 100644 (file)
@@ -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;