[systemd-commits] 5 commits - Makefile.am src/core src/libsystemd-dhcp src/network src/shared src/udev

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Feb 20 13:13:42 PST 2014


 Makefile.am                              |   16 +-
 src/core/condition.c                     |  244 +++----------------------------
 src/core/condition.h                     |   48 ------
 src/libsystemd-dhcp/sd-dhcp-client.c     |    4 
 src/network/.gitignore                   |    3 
 src/network/networkd-gperf.gperf         |   44 -----
 src/network/networkd-netdev-gperf.gperf  |   24 +++
 src/network/networkd-netdev.c            |   10 +
 src/network/networkd-network-gperf.gperf |   43 +++++
 src/network/networkd-network.c           |    5 
 src/network/networkd.h                   |   14 +
 src/shared/condition-util.c              |  243 ++++++++++++++++++++++++++++++
 src/shared/condition-util.h              |   77 +++++++++
 src/shared/net-util.c                    |   54 ++++++
 src/shared/net-util.h                    |    9 +
 src/udev/net/link-config-gperf.gperf     |   31 ++-
 src/udev/net/link-config.c               |    1 
 src/udev/net/link-config.h               |    4 
 18 files changed, 541 insertions(+), 333 deletions(-)

New commits:
commit 2333154a2b81bcb9dbf034ad004d975561e8b79d
Author: Umut Tezduyar Lindskog <umut.tezduyar at axis.com>
Date:   Thu Feb 20 21:04:03 2014 +0100

    sd-dhcp-client: prevent timer related memory leaks

diff --git a/src/libsystemd-dhcp/sd-dhcp-client.c b/src/libsystemd-dhcp/sd-dhcp-client.c
index ec2b53f..53abe22 100644
--- a/src/libsystemd-dhcp/sd-dhcp-client.c
+++ b/src/libsystemd-dhcp/sd-dhcp-client.c
@@ -392,6 +392,8 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
 
         next_timeout += (random_u32() & 0x1fffff);
 
+        client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+
         r = sd_event_add_monotonic(client->event,
                                      &client->timeout_resend,
                                      next_timeout,
@@ -477,6 +479,8 @@ static int client_initialize_events(sd_dhcp_client *client,
         if (r < 0)
                 goto error;
 
+        client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+
         r = sd_event_add_monotonic(client->event,
                                    &client->timeout_resend,
                                    usec, 0,

commit c0dda18697e0994272c0c9616d36f6777b60e2c7
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Feb 20 19:56:50 2014 +0100

    networkd: netdev - allow filtering on kernel cmdline, host and virt

diff --git a/Makefile.am b/Makefile.am
index ee7dd2d..6b6f6db 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3925,7 +3925,8 @@ systemd_networkd_SOURCES = \
 	src/network/networkd-manager.c
 
 nodist_systemd_networkd_SOURCES = \
-	src/network/networkd-gperf.c
+	src/network/networkd-network-gperf.c \
+	src/network/networkd-netdev-gperf.c
 
 systemd_networkd_LDADD = \
 	libudev-internal.la \
@@ -3949,7 +3950,8 @@ test_network_SOURCES = \
 	src/network/networkd-address.c \
 	src/network/networkd-route.c \
 	src/network/networkd-manager.c \
-	src/network/networkd-gperf.c
+	src/network/networkd-network-gperf.c \
+	src/network/networkd-netdev-gperf.c
 
 test_network_LDADD = \
 	libudev-internal.la \
@@ -3962,11 +3964,13 @@ tests += \
 	test-network
 
 EXTRA_DIST += \
-	src/network/networkd-gperf.gperf \
+	src/network/networkd-network-gperf.gperf \
+	src/network/networkd-netdev-gperf.gperf \
 	units/systemd-networkd.service.in
 
 CLEANFILES += \
-	src/network/networkd-gperf.c
+	src/network/networkd-network-gperf.c \
+	src/network/networkd-netdev-gperf.c
 endif
 
 # ------------------------------------------------------------------------------
diff --git a/src/network/.gitignore b/src/network/.gitignore
index b2a8c1a..8858596 100644
--- a/src/network/.gitignore
+++ b/src/network/.gitignore
@@ -1 +1,2 @@
-/networkd-gperf.c
+/networkd-network-gperf.c
+/networkd-netdev-gperf.c
diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
deleted file mode 100644
index cfffb33..0000000
--- a/src/network/networkd-gperf.gperf
+++ /dev/null
@@ -1,47 +0,0 @@
-%{
-#include <stddef.h>
-#include "conf-parser.h"
-#include "networkd.h"
-#include "net-util.h"
-%}
-struct ConfigPerfItem;
-%null_strings
-%language=ANSI-C
-%define slot-name section_and_lvalue
-%define hash-function-name network_gperf_hash
-%define lookup-function-name network_gperf_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%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.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)
-Network.Description,       config_parse_string,                0,                             offsetof(Network, description)
-Network.Bridge,            config_parse_bridge,                0,                             offsetof(Network, bridge)
-Network.Bond,              config_parse_bond,                  0,                             offsetof(Network, bond)
-Network.VLAN,              config_parse_vlan,                  0,                             offsetof(Network, vlans)
-Network.DHCP,              config_parse_bool,                  0,                             offsetof(Network, dhcp)
-Network.Address,           config_parse_address,               0,                             0
-Network.Gateway,           config_parse_gateway,               0,                             0
-Network.DNS,               config_parse_dns,                   0,                             offsetof(Network, dns)
-Address.Address,           config_parse_address,               0,                             0
-Address.Broadcast,         config_parse_broadcast,             0,                             0
-Address.Label,             config_parse_label,                 0,                             0
-Route.Gateway,             config_parse_gateway,               0,                             0
-Route.Destination,         config_parse_destination,           0,                             0
-DHCPv4.UseDNS,             config_parse_bool,                  0,                             offsetof(Network, dhcp_dns)
-DHCPv4.UseMTU,             config_parse_bool,                  0,                             offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname,        config_parse_bool,                  0,                             offsetof(Network, dhcp_hostname)
-DHCPv4.UseDomainName,      config_parse_bool,                  0,                             offsetof(Network, dhcp_domainname)
-DHCPv4.CriticalConnection, config_parse_bool,                  0,                             offsetof(Network, dhcp_critical)
-NetDev.Description,        config_parse_string,                0,                             offsetof(NetDev, description)
-NetDev.Name,               config_parse_ifname,                0,                             offsetof(NetDev, name)
-NetDev.Kind,               config_parse_netdev_kind,           0,                             offsetof(NetDev, kind)
-VLAN.Id,                   config_parse_uint64,                0,                             offsetof(NetDev, vlanid)
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
new file mode 100644
index 0000000..cdaacb1
--- /dev/null
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -0,0 +1,24 @@
+%{
+#include <stddef.h>
+#include "conf-parser.h"
+#include "networkd.h"
+#include "net-util.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name network_netdev_gperf_hash
+%define lookup-function-name network_netdev_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+Match.Host,              config_parse_net_condition,         CONDITION_HOST,                offsetof(NetDev, condition_host)
+Match.Virtualization,    config_parse_net_condition,         CONDITION_VIRTUALIZATION,      offsetof(NetDev, condition_virt)
+Match.KernelCommandLine, config_parse_net_condition,         CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, condition_kernel)
+NetDev.Description,      config_parse_string,                0,                             offsetof(NetDev, description)
+NetDev.Name,             config_parse_ifname,                0,                             offsetof(NetDev, name)
+NetDev.Kind,             config_parse_netdev_kind,           0,                             offsetof(NetDev, kind)
+VLAN.Id,                 config_parse_uint64,                0,                             offsetof(NetDev, vlanid)
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ea6da69..773163d 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -337,8 +337,8 @@ static int netdev_load_one(Manager *manager, const char *filename) {
         netdev->kind = _NETDEV_KIND_INVALID;
         netdev->vlanid = VLANID_MAX + 1;
 
-        r = config_parse(NULL, filename, file, "NetDev\0VLAN\0", config_item_perf_lookup,
-                        (void*) network_gperf_lookup, false, false, netdev);
+        r = config_parse(NULL, filename, file, "Match\0NetDev\0VLAN\0", config_item_perf_lookup,
+                        (void*) network_netdev_gperf_lookup, false, false, netdev);
         if (r < 0) {
                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
                 return r;
@@ -363,6 +363,12 @@ static int netdev_load_one(Manager *manager, const char *filename) {
         if (!netdev->filename)
                 return log_oom();
 
+        if (net_match_config(NULL, NULL, NULL, NULL, NULL,
+                             netdev->condition_host, netdev->condition_virt,
+                             netdev->condition_kernel, NULL, NULL, NULL,
+                             NULL, NULL) <= 0)
+                return 0;
+
         r = hashmap_put(netdev->manager->netdevs, netdev->name, netdev);
         if (r < 0)
                 return r;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
new file mode 100644
index 0000000..011f7e9
--- /dev/null
+++ b/src/network/networkd-network-gperf.gperf
@@ -0,0 +1,43 @@
+%{
+#include <stddef.h>
+#include "conf-parser.h"
+#include "networkd.h"
+#include "net-util.h"
+%}
+struct ConfigPerfItem;
+%null_strings
+%language=ANSI-C
+%define slot-name section_and_lvalue
+%define hash-function-name network_network_gperf_hash
+%define lookup-function-name network_network_gperf_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%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.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)
+Network.Description,         config_parse_string,                0,                             offsetof(Network, description)
+Network.Bridge,              config_parse_bridge,                0,                             offsetof(Network, bridge)
+Network.Bond,                config_parse_bond,                  0,                             offsetof(Network, bond)
+Network.VLAN,                config_parse_vlan,                  0,                             offsetof(Network, vlans)
+Network.DHCP,                config_parse_bool,                  0,                             offsetof(Network, dhcp)
+Network.Address,             config_parse_address,               0,                             0
+Network.Gateway,             config_parse_gateway,               0,                             0
+Network.DNS,                 config_parse_dns,                   0,                             offsetof(Network, dns)
+Address.Address,             config_parse_address,               0,                             0
+Address.Broadcast,           config_parse_broadcast,             0,                             0
+Address.Label,               config_parse_label,                 0,                             0
+Route.Gateway,               config_parse_gateway,               0,                             0
+Route.Destination,           config_parse_destination,           0,                             0
+DHCPv4.UseDNS,               config_parse_bool,                  0,                             offsetof(Network, dhcp_dns)
+DHCPv4.UseMTU,               config_parse_bool,                  0,                             offsetof(Network, dhcp_mtu)
+DHCPv4.UseHostname,          config_parse_bool,                  0,                             offsetof(Network, dhcp_hostname)
+DHCPv4.UseDomainName,        config_parse_bool,                  0,                             offsetof(Network, dhcp_domainname)
+DHCPv4.CriticalConnection,   config_parse_bool,                  0,                             offsetof(Network, dhcp_critical)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index fd1befc..3119471 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -74,7 +74,7 @@ static int network_load_one(Manager *manager, const char *filename) {
         network->dhcp_domainname = true;
 
         r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
-                        (void*) network_gperf_lookup, false, false, network);
+                        (void*) network_network_gperf_lookup, false, false, network);
         if (r < 0) {
                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
                 return r;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index f16226a..8008df5 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -71,6 +71,10 @@ struct NetDev {
 
         char *filename;
 
+        Condition *condition_host;
+        Condition *condition_virt;
+        Condition *condition_kernel;
+
         char *description;
         char *name;
         NetDevKind kind;
@@ -242,6 +246,9 @@ NetDevKind netdev_kind_from_string(const char *d) _pure_;
 
 int config_parse_netdev_kind(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);
 
+/* gperf */
+const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length);
+
 /* Network */
 
 int network_load(Manager *manager);
@@ -267,8 +274,7 @@ int config_parse_vlan(const char *unit, const char *filename, unsigned line,
                       int ltype, const char *rvalue, void *data, void *userdata);
 
 /* gperf */
-
-const struct ConfigPerfItem* network_gperf_lookup(const char *key, unsigned length);
+const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
 
 /* Route */
 int route_new_static(Network *network, unsigned section, Route **ret);

commit 2cc412b59353576cece2d5b30c6a39c70552f0a0
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Feb 20 19:39:49 2014 +0100

    network/link: Match - filter on kernel cmdline, host and virt

diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf
index ecc5ca0..cfffb33 100644
--- a/src/network/networkd-gperf.gperf
+++ b/src/network/networkd-gperf.gperf
@@ -15,30 +15,33 @@ struct ConfigPerfItem;
 %struct-type
 %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)
-Network.Description,       config_parse_string,           0,       offsetof(Network, description)
-Network.Bridge,            config_parse_bridge,           0,       offsetof(Network, bridge)
-Network.Bond,              config_parse_bond,             0,       offsetof(Network, bond)
-Network.VLAN,              config_parse_vlan,             0,       offsetof(Network, vlans)
-Network.DHCP,              config_parse_bool,             0,       offsetof(Network, dhcp)
-Network.Address,           config_parse_address,          0,       0
-Network.Gateway,           config_parse_gateway,          0,       0
-Network.DNS,               config_parse_dns,              0,       offsetof(Network, dns)
-Address.Address,           config_parse_address,          0,       0
-Address.Broadcast,         config_parse_broadcast,        0,       0
-Address.Label,             config_parse_label,            0,       0
-Route.Gateway,             config_parse_gateway,          0,       0
-Route.Destination,         config_parse_destination,      0,       0
-DHCPv4.UseDNS,             config_parse_bool,             0,       offsetof(Network, dhcp_dns)
-DHCPv4.UseMTU,             config_parse_bool,             0,       offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname,        config_parse_bool,             0,       offsetof(Network, dhcp_hostname)
-DHCPv4.UseDomainName,      config_parse_bool,             0,       offsetof(Network, dhcp_domainname)
-DHCPv4.CriticalConnection, config_parse_bool,             0,       offsetof(Network, dhcp_critical)
-NetDev.Description,        config_parse_string,           0,       offsetof(NetDev, description)
-NetDev.Name,               config_parse_ifname,           0,       offsetof(NetDev, name)
-NetDev.Kind,               config_parse_netdev_kind,      0,       offsetof(NetDev, kind)
-VLAN.Id,                   config_parse_uint64,           0,       offsetof(NetDev, vlanid)
+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.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)
+Network.Description,       config_parse_string,                0,                             offsetof(Network, description)
+Network.Bridge,            config_parse_bridge,                0,                             offsetof(Network, bridge)
+Network.Bond,              config_parse_bond,                  0,                             offsetof(Network, bond)
+Network.VLAN,              config_parse_vlan,                  0,                             offsetof(Network, vlans)
+Network.DHCP,              config_parse_bool,                  0,                             offsetof(Network, dhcp)
+Network.Address,           config_parse_address,               0,                             0
+Network.Gateway,           config_parse_gateway,               0,                             0
+Network.DNS,               config_parse_dns,                   0,                             offsetof(Network, dns)
+Address.Address,           config_parse_address,               0,                             0
+Address.Broadcast,         config_parse_broadcast,             0,                             0
+Address.Label,             config_parse_label,                 0,                             0
+Route.Gateway,             config_parse_gateway,               0,                             0
+Route.Destination,         config_parse_destination,           0,                             0
+DHCPv4.UseDNS,             config_parse_bool,                  0,                             offsetof(Network, dhcp_dns)
+DHCPv4.UseMTU,             config_parse_bool,                  0,                             offsetof(Network, dhcp_mtu)
+DHCPv4.UseHostname,        config_parse_bool,                  0,                             offsetof(Network, dhcp_hostname)
+DHCPv4.UseDomainName,      config_parse_bool,                  0,                             offsetof(Network, dhcp_domainname)
+DHCPv4.CriticalConnection, config_parse_bool,                  0,                             offsetof(Network, dhcp_critical)
+NetDev.Description,        config_parse_string,                0,                             offsetof(NetDev, description)
+NetDev.Name,               config_parse_ifname,                0,                             offsetof(NetDev, name)
+NetDev.Kind,               config_parse_netdev_kind,           0,                             offsetof(NetDev, kind)
+VLAN.Id,                   config_parse_uint64,                0,                             offsetof(NetDev, vlanid)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index a470c22..fd1befc 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -175,7 +175,8 @@ int network_get(Manager *manager, struct udev_device *device, Network **ret) {
         LIST_FOREACH(networks, network, manager->networks) {
                 if (net_match_config(network->match_mac, network->match_path,
                                         network->match_driver, network->match_type,
-                                        network->match_name,
+                                        network->match_name, network->match_host,
+                                        network->match_virt, network->match_kernel,
                                         udev_device_get_sysattr_value(device, "address"),
                                         udev_device_get_property_value(device, "ID_PATH"),
                                         udev_device_get_driver(udev_device_get_parent(device)),
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 5a1bf1a..f16226a 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -32,6 +32,7 @@
 #include "rtnl-util.h"
 #include "hashmap.h"
 #include "list.h"
+#include "condition-util.h"
 
 typedef struct NetDev NetDev;
 typedef struct Network Network;
@@ -92,6 +93,9 @@ struct Network {
         char *match_driver;
         char *match_type;
         char *match_name;
+        Condition *match_host;
+        Condition *match_virt;
+        Condition *match_kernel;
 
         char *description;
         NetDev *bridge;
diff --git a/src/shared/net-util.c b/src/shared/net-util.c
index ba21ae4..06c50b5 100644
--- a/src/shared/net-util.c
+++ b/src/shared/net-util.c
@@ -28,18 +28,31 @@
 #include "utf8.h"
 #include "util.h"
 #include "conf-parser.h"
+#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,
+                      Condition *match_host,
+                      Condition *match_virt,
+                      Condition *match_kernel,
                       const char *dev_mac,
                       const char *dev_path,
                       const char *dev_driver,
                       const char *dev_type,
                       const char *dev_name) {
 
+        if (match_host && !condition_test_host(match_host))
+                return 0;
+
+        if (match_virt && !condition_test_virtualization(match_virt))
+                return 0;
+
+        if (match_kernel && !condition_test_kernel_command_line(match_kernel))
+                return 0;
+
         if (match_mac && (!dev_mac || memcmp(match_mac, ether_aton(dev_mac), ETH_ALEN)))
                 return 0;
 
@@ -64,6 +77,47 @@ unsigned net_netmask_to_prefixlen(const struct in_addr *addr) {
         return 32 - u32ctz(be32toh(addr->s_addr));
 }
 
+int config_parse_net_condition(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) {
+
+        ConditionType cond = ltype;
+        Condition **ret = data;
+        bool negate;
+        Condition *c;
+        _cleanup_free_ char *s = NULL;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        negate = rvalue[0] == '!';
+        if (negate)
+                rvalue++;
+
+        s = strdup(rvalue);
+        if (!s)
+                return log_oom();
+
+        c = condition_new(cond, s, false, negate);
+        if (!c)
+                return log_oom();
+
+        if (*ret)
+                condition_free(*ret);
+
+        *ret = c;
+        return 0;
+}
+
 int config_parse_ifname(const char *unit,
                         const char *filename,
                         unsigned line,
diff --git a/src/shared/net-util.h b/src/shared/net-util.h
index 0ec04db..a20b62e 100644
--- a/src/shared/net-util.h
+++ b/src/shared/net-util.h
@@ -25,11 +25,16 @@
 #include <netinet/in.h>
 #include <stdbool.h>
 
+#include "condition-util.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,
+                      Condition *match_host,
+                      Condition *match_virt,
+                      Condition *match_kernel,
                       const char *dev_mac,
                       const char *dev_path,
                       const char *dev_driver,
@@ -38,6 +43,10 @@ bool net_match_config(const struct ether_addr *match_mac,
 
 unsigned net_netmask_to_prefixlen(const struct in_addr *netmask);
 
+int config_parse_net_condition(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_hwaddr(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/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 950fb15..ffc1b27 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -16,17 +16,20 @@ struct ConfigPerfItem;
 %struct-type
 %includes
 %%
-Match.MACAddress,                   config_parse_hwaddr,        0, offsetof(link_config, match_mac)
-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)
-Link.Description,                   config_parse_string,        0, offsetof(link_config, description)
-Link.MACAddressPolicy,              config_parse_mac_policy,    0, offsetof(link_config, mac_policy)
-Link.MACAddress,                    config_parse_hwaddr,        0, offsetof(link_config, mac)
-Link.NamePolicy,                    config_parse_name_policy,   0, offsetof(link_config, name_policy)
-Link.Name,                          config_parse_ifname,        0, offsetof(link_config, name)
-Link.Alias,                         config_parse_ifalias,       0, offsetof(link_config, alias)
-Link.MTU,                           config_parse_unsigned,      0, offsetof(link_config, mtu)
-Link.SpeedMBytes,                   config_parse_unsigned,      0, offsetof(link_config, speed)
-Link.Duplex,                        config_parse_duplex,        0, offsetof(link_config, duplex)
-Link.WakeOnLan,                     config_parse_wol,           0, offsetof(link_config, wol)
+Match.MACAddress,          config_parse_hwaddr,        0,                             offsetof(link_config, match_mac)
+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.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)
+Link.Description,          config_parse_string,        0,                             offsetof(link_config, description)
+Link.MACAddressPolicy,     config_parse_mac_policy,    0,                             offsetof(link_config, mac_policy)
+Link.MACAddress,           config_parse_hwaddr,        0,                             offsetof(link_config, mac)
+Link.NamePolicy,           config_parse_name_policy,   0,                             offsetof(link_config, name_policy)
+Link.Name,                 config_parse_ifname,        0,                             offsetof(link_config, name)
+Link.Alias,                config_parse_ifalias,       0,                             offsetof(link_config, alias)
+Link.MTU,                  config_parse_unsigned,      0,                             offsetof(link_config, mtu)
+Link.SpeedMBytes,          config_parse_unsigned,      0,                             offsetof(link_config, speed)
+Link.Duplex,               config_parse_duplex,        0,                             offsetof(link_config, duplex)
+Link.WakeOnLan,            config_parse_wol,           0,                             offsetof(link_config, wol)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 587eeef..15bea4f 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -242,6 +242,7 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, link_confi
 
                 if (net_match_config(link->match_mac, link->match_path,
                                      link->match_driver, link->match_type, NULL,
+                                     link->match_host, link->match_virt, link->match_kernel,
                                      udev_device_get_sysattr_value(device, "address"),
                                      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 4fc8963..0dc156d 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -23,6 +23,7 @@
 
 #include "ethtool-util.h"
 
+#include "condition-util.h"
 #include "libudev.h"
 #include "util.h"
 #include "list.h"
@@ -54,6 +55,9 @@ struct link_config {
         char *match_path;
         char *match_driver;
         char *match_type;
+        Condition *match_host;
+        Condition *match_virt;
+        Condition *match_kernel;
 
         char *description;
         struct ether_addr *mac;

commit b77c08e06b67d5b1dd8aaf67b732e93851d8ae43
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Feb 20 19:26:54 2014 +0100

    condition: split out most of condition handling into libsystemd-shard
    
    The parts that require linknig to libcap, libselinux and friends stays in libsystemd-core.

diff --git a/Makefile.am b/Makefile.am
index 03a65bf..ee7dd2d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -766,7 +766,9 @@ libsystemd_shared_la_SOURCES = \
 	src/shared/audit.c \
 	src/shared/audit.h \
 	src/shared/xml.c \
-	src/shared/xml.h
+	src/shared/xml.h \
+	src/shared/condition-util.c \
+	src/shared/condition-util.h
 
 nodist_libsystemd_shared_la_SOURCES = \
 	src/shared/errno-from-name.h \
diff --git a/src/core/condition.c b/src/core/condition.c
index 35de996..658e8d6 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -39,126 +39,6 @@
 #include "ima-util.h"
 #include "selinux-util.h"
 
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
-        Condition *c;
-
-        assert(type < _CONDITION_TYPE_MAX);
-
-        c = new0(Condition, 1);
-        if (!c)
-                return NULL;
-
-        c->type = type;
-        c->trigger = trigger;
-        c->negate = negate;
-
-        if (parameter) {
-                c->parameter = strdup(parameter);
-                if (!c->parameter) {
-                        free(c);
-                        return NULL;
-                }
-        }
-
-        return c;
-}
-
-void condition_free(Condition *c) {
-        assert(c);
-
-        free(c->parameter);
-        free(c);
-}
-
-void condition_free_list(Condition *first) {
-        Condition *c, *n;
-
-        LIST_FOREACH_SAFE(conditions, c, n, first)
-                condition_free(c);
-}
-
-static bool condition_test_kernel_command_line(Condition *c) {
-        char *line, *w, *state, *word = NULL;
-        bool equal;
-        int r;
-        size_t l, pl;
-        bool found = false;
-
-        assert(c);
-        assert(c->parameter);
-        assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
-
-        r = proc_cmdline(&line);
-        if (r < 0)
-                log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
-        if (r <= 0)
-                return c->negate;
-
-        equal = !!strchr(c->parameter, '=');
-        pl = strlen(c->parameter);
-
-        FOREACH_WORD_QUOTED(w, l, line, state) {
-
-                free(word);
-                word = strndup(w, l);
-                if (!word)
-                        break;
-
-                if (equal) {
-                        if (streq(word, c->parameter)) {
-                                found = true;
-                                break;
-                        }
-                } else {
-                        if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) {
-                                found = true;
-                                break;
-                        }
-                }
-
-        }
-
-        free(word);
-        free(line);
-
-        return found == !c->negate;
-}
-
-static bool condition_test_virtualization(Condition *c) {
-        int b;
-        Virtualization v;
-        const char *id;
-
-        assert(c);
-        assert(c->parameter);
-        assert(c->type == CONDITION_VIRTUALIZATION);
-
-        v = detect_virtualization(&id);
-        if (v < 0) {
-                log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
-                return c->negate;
-        }
-
-        /* First, compare with yes/no */
-        b = parse_boolean(c->parameter);
-
-        if (v > 0 && b > 0)
-                return !c->negate;
-
-        if (v == 0 && b == 0)
-                return !c->negate;
-
-        /* Then, compare categorization */
-        if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
-                return !c->negate;
-
-        if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
-                return !c->negate;
-
-        /* Finally compare id */
-        return (v > 0 && streq(c->parameter, id)) == !c->negate;
-}
-
 static bool condition_test_security(Condition *c) {
         assert(c);
         assert(c->parameter);
@@ -211,49 +91,6 @@ static bool condition_test_capability(Condition *c) {
         return !!(capabilities & (1ULL << value)) == !c->negate;
 }
 
-static bool condition_test_host(Condition *c) {
-        sd_id128_t x, y;
-        char *h;
-        int r;
-        bool b;
-
-        assert(c);
-        assert(c->parameter);
-        assert(c->type == CONDITION_HOST);
-
-        if (sd_id128_from_string(c->parameter, &x) >= 0) {
-
-                r = sd_id128_get_machine(&y);
-                if (r < 0)
-                        return c->negate;
-
-                return sd_id128_equal(x, y);
-        }
-
-        h = gethostname_malloc();
-        if (!h)
-                return c->negate;
-
-        b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
-        free(h);
-
-        return b == !c->negate;
-}
-
-static bool condition_test_ac_power(Condition *c) {
-        int r;
-
-        assert(c);
-        assert(c->parameter);
-        assert(c->type == CONDITION_AC_POWER);
-
-        r = parse_boolean(c->parameter);
-        if (r < 0)
-                return !c->negate;
-
-        return ((on_ac_power() != 0) == !!r) == !c->negate;
-}
-
 static bool condition_test(Condition *c) {
         assert(c);
 
@@ -373,48 +210,3 @@ bool condition_test_list(const char *unit, Condition *first) {
 
         return triggered != 0;
 }
-
-void condition_dump(Condition *c, FILE *f, const char *prefix) {
-        assert(c);
-        assert(f);
-
-        if (!prefix)
-                prefix = "";
-
-        fprintf(f,
-                "%s\t%s: %s%s%s %s\n",
-                prefix,
-                condition_type_to_string(c->type),
-                c->trigger ? "|" : "",
-                c->negate ? "!" : "",
-                c->parameter,
-                c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
-}
-
-void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
-        Condition *c;
-
-        LIST_FOREACH(conditions, c, first)
-                condition_dump(c, f, prefix);
-}
-
-static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
-        [CONDITION_PATH_EXISTS] = "ConditionPathExists",
-        [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
-        [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
-        [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
-        [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
-        [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
-        [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
-        [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
-        [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
-        [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
-        [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
-        [CONDITION_SECURITY] = "ConditionSecurity",
-        [CONDITION_CAPABILITY] = "ConditionCapability",
-        [CONDITION_HOST] = "ConditionHost",
-        [CONDITION_AC_POWER] = "ConditionACPower",
-        [CONDITION_NULL] = "ConditionNull"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
diff --git a/src/core/condition.h b/src/core/condition.h
index 1813b73..6dd77bb 100644
--- a/src/core/condition.h
+++ b/src/core/condition.h
@@ -21,52 +21,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <stdbool.h>
-
-#include "list.h"
-
-typedef enum ConditionType {
-        CONDITION_PATH_EXISTS,
-        CONDITION_PATH_EXISTS_GLOB,
-        CONDITION_PATH_IS_DIRECTORY,
-        CONDITION_PATH_IS_SYMBOLIC_LINK,
-        CONDITION_PATH_IS_MOUNT_POINT,
-        CONDITION_PATH_IS_READ_WRITE,
-        CONDITION_DIRECTORY_NOT_EMPTY,
-        CONDITION_FILE_NOT_EMPTY,
-        CONDITION_FILE_IS_EXECUTABLE,
-        CONDITION_KERNEL_COMMAND_LINE,
-        CONDITION_VIRTUALIZATION,
-        CONDITION_SECURITY,
-        CONDITION_CAPABILITY,
-        CONDITION_HOST,
-        CONDITION_AC_POWER,
-        CONDITION_NULL,
-        _CONDITION_TYPE_MAX,
-        _CONDITION_TYPE_INVALID = -1
-} ConditionType;
-
-typedef struct Condition {
-        ConditionType type;
-
-        bool trigger:1;
-        bool negate:1;
-
-        char *parameter;
-
-        int state;
-
-        LIST_FIELDS(struct Condition, conditions);
-} Condition;
-
-Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
-void condition_free(Condition *c);
-void condition_free_list(Condition *c);
+#include "condition-util.h"
 
 bool condition_test_list(const char *unit, Condition *c);
-
-void condition_dump(Condition *c, FILE *f, const char *prefix);
-void condition_dump_list(Condition *c, FILE *f, const char *prefix);
-
-const char* condition_type_to_string(ConditionType t) _const_;
-int condition_type_from_string(const char *s) _pure_;
diff --git a/src/shared/condition-util.c b/src/shared/condition-util.c
new file mode 100644
index 0000000..d31c4bf
--- /dev/null
+++ b/src/shared/condition-util.c
@@ -0,0 +1,243 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/statvfs.h>
+#include <fnmatch.h>
+
+#include <systemd/sd-id128.h>
+#include "util.h"
+#include "condition-util.h"
+#include "virt.h"
+#include "path-util.h"
+#include "fileio.h"
+#include "unit.h"
+
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
+        Condition *c;
+
+        assert(type < _CONDITION_TYPE_MAX);
+
+        c = new0(Condition, 1);
+        if (!c)
+                return NULL;
+
+        c->type = type;
+        c->trigger = trigger;
+        c->negate = negate;
+
+        if (parameter) {
+                c->parameter = strdup(parameter);
+                if (!c->parameter) {
+                        free(c);
+                        return NULL;
+                }
+        }
+
+        return c;
+}
+
+void condition_free(Condition *c) {
+        assert(c);
+
+        free(c->parameter);
+        free(c);
+}
+
+void condition_free_list(Condition *first) {
+        Condition *c, *n;
+
+        LIST_FOREACH_SAFE(conditions, c, n, first)
+                condition_free(c);
+}
+
+bool condition_test_kernel_command_line(Condition *c) {
+        char *line, *w, *state, *word = NULL;
+        bool equal;
+        int r;
+        size_t l, pl;
+        bool found = false;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
+
+        r = proc_cmdline(&line);
+        if (r < 0)
+                log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
+        if (r <= 0)
+                return c->negate;
+
+        equal = !!strchr(c->parameter, '=');
+        pl = strlen(c->parameter);
+
+        FOREACH_WORD_QUOTED(w, l, line, state) {
+
+                free(word);
+                word = strndup(w, l);
+                if (!word)
+                        break;
+
+                if (equal) {
+                        if (streq(word, c->parameter)) {
+                                found = true;
+                                break;
+                        }
+                } else {
+                        if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) {
+                                found = true;
+                                break;
+                        }
+                }
+
+        }
+
+        free(word);
+        free(line);
+
+        return found == !c->negate;
+}
+
+bool condition_test_virtualization(Condition *c) {
+        int b;
+        Virtualization v;
+        const char *id;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_VIRTUALIZATION);
+
+        v = detect_virtualization(&id);
+        if (v < 0) {
+                log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
+                return c->negate;
+        }
+
+        /* First, compare with yes/no */
+        b = parse_boolean(c->parameter);
+
+        if (v > 0 && b > 0)
+                return !c->negate;
+
+        if (v == 0 && b == 0)
+                return !c->negate;
+
+        /* Then, compare categorization */
+        if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
+                return !c->negate;
+
+        if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
+                return !c->negate;
+
+        /* Finally compare id */
+        return (v > 0 && streq(c->parameter, id)) == !c->negate;
+}
+
+bool condition_test_host(Condition *c) {
+        sd_id128_t x, y;
+        char *h;
+        int r;
+        bool b;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_HOST);
+
+        if (sd_id128_from_string(c->parameter, &x) >= 0) {
+
+                r = sd_id128_get_machine(&y);
+                if (r < 0)
+                        return c->negate;
+
+                return sd_id128_equal(x, y);
+        }
+
+        h = gethostname_malloc();
+        if (!h)
+                return c->negate;
+
+        b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
+        free(h);
+
+        return b == !c->negate;
+}
+
+bool condition_test_ac_power(Condition *c) {
+        int r;
+
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_AC_POWER);
+
+        r = parse_boolean(c->parameter);
+        if (r < 0)
+                return !c->negate;
+
+        return ((on_ac_power() != 0) == !!r) == !c->negate;
+}
+
+void condition_dump(Condition *c, FILE *f, const char *prefix) {
+        assert(c);
+        assert(f);
+
+        if (!prefix)
+                prefix = "";
+
+        fprintf(f,
+                "%s\t%s: %s%s%s %s\n",
+                prefix,
+                condition_type_to_string(c->type),
+                c->trigger ? "|" : "",
+                c->negate ? "!" : "",
+                c->parameter,
+                c->state < 0 ? "failed" : c->state > 0 ? "succeeded" : "untested");
+}
+
+void condition_dump_list(Condition *first, FILE *f, const char *prefix) {
+        Condition *c;
+
+        LIST_FOREACH(conditions, c, first)
+                condition_dump(c, f, prefix);
+}
+
+static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
+        [CONDITION_PATH_EXISTS] = "ConditionPathExists",
+        [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
+        [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
+        [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
+        [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
+        [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
+        [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
+        [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
+        [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
+        [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
+        [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
+        [CONDITION_SECURITY] = "ConditionSecurity",
+        [CONDITION_CAPABILITY] = "ConditionCapability",
+        [CONDITION_HOST] = "ConditionHost",
+        [CONDITION_AC_POWER] = "ConditionACPower",
+        [CONDITION_NULL] = "ConditionNull"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
diff --git a/src/shared/condition-util.h b/src/shared/condition-util.h
new file mode 100644
index 0000000..85d4d5b
--- /dev/null
+++ b/src/shared/condition-util.h
@@ -0,0 +1,77 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "list.h"
+#include "macro.h"
+
+typedef enum ConditionType {
+        CONDITION_PATH_EXISTS,
+        CONDITION_PATH_EXISTS_GLOB,
+        CONDITION_PATH_IS_DIRECTORY,
+        CONDITION_PATH_IS_SYMBOLIC_LINK,
+        CONDITION_PATH_IS_MOUNT_POINT,
+        CONDITION_PATH_IS_READ_WRITE,
+        CONDITION_DIRECTORY_NOT_EMPTY,
+        CONDITION_FILE_NOT_EMPTY,
+        CONDITION_FILE_IS_EXECUTABLE,
+        CONDITION_KERNEL_COMMAND_LINE,
+        CONDITION_VIRTUALIZATION,
+        CONDITION_SECURITY,
+        CONDITION_CAPABILITY,
+        CONDITION_HOST,
+        CONDITION_AC_POWER,
+        CONDITION_NULL,
+        _CONDITION_TYPE_MAX,
+        _CONDITION_TYPE_INVALID = -1
+} ConditionType;
+
+typedef struct Condition {
+        ConditionType type;
+
+        bool trigger:1;
+        bool negate:1;
+
+        char *parameter;
+
+        int state;
+
+        LIST_FIELDS(struct Condition, conditions);
+} Condition;
+
+Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
+void condition_free(Condition *c);
+void condition_free_list(Condition *c);
+
+bool condition_test_kernel_command_line(Condition *c);
+bool condition_test_virtualization(Condition *c);
+bool condition_test_host(Condition *c);
+bool condition_test_ac_power(Condition *c);
+
+void condition_dump(Condition *c, FILE *f, const char *prefix);
+void condition_dump_list(Condition *c, FILE *f, const char *prefix);
+
+const char* condition_type_to_string(ConditionType t) _const_;
+int condition_type_from_string(const char *s) _pure_;

commit afc50ea84e40d6a3f27ad5bfb5161e2d9b431275
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Feb 20 19:09:49 2014 +0100

    condition: refactor a bit
    
    No functional change, just move code around a bit to make it simpler to split out
    some functions.

diff --git a/src/core/condition.c b/src/core/condition.c
index 436e784..35de996 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -77,23 +77,25 @@ void condition_free_list(Condition *first) {
                 condition_free(c);
 }
 
-static bool test_kernel_command_line(const char *parameter) {
+static bool condition_test_kernel_command_line(Condition *c) {
         char *line, *w, *state, *word = NULL;
         bool equal;
         int r;
         size_t l, pl;
         bool found = false;
 
-        assert(parameter);
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_KERNEL_COMMAND_LINE);
 
         r = proc_cmdline(&line);
         if (r < 0)
                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
         if (r <= 0)
-                return false;
+                return c->negate;
 
-        equal = !!strchr(parameter, '=');
-        pl = strlen(parameter);
+        equal = !!strchr(c->parameter, '=');
+        pl = strlen(c->parameter);
 
         FOREACH_WORD_QUOTED(w, l, line, state) {
 
@@ -103,12 +105,12 @@ static bool test_kernel_command_line(const char *parameter) {
                         break;
 
                 if (equal) {
-                        if (streq(word, parameter)) {
+                        if (streq(word, c->parameter)) {
                                 found = true;
                                 break;
                         }
                 } else {
-                        if (startswith(word, parameter) && (word[pl] == '=' || word[pl] == 0)) {
+                        if (startswith(word, c->parameter) && (word[pl] == '=' || word[pl] == 0)) {
                                 found = true;
                                 break;
                         }
@@ -119,71 +121,81 @@ static bool test_kernel_command_line(const char *parameter) {
         free(word);
         free(line);
 
-        return found;
+        return found == !c->negate;
 }
 
-static bool test_virtualization(const char *parameter) {
+static bool condition_test_virtualization(Condition *c) {
         int b;
         Virtualization v;
         const char *id;
 
-        assert(parameter);
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_VIRTUALIZATION);
 
         v = detect_virtualization(&id);
         if (v < 0) {
                 log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
-                return false;
+                return c->negate;
         }
 
         /* First, compare with yes/no */
-        b = parse_boolean(parameter);
+        b = parse_boolean(c->parameter);
 
         if (v > 0 && b > 0)
-                return true;
+                return !c->negate;
 
         if (v == 0 && b == 0)
-                return true;
+                return !c->negate;
 
         /* Then, compare categorization */
-        if (v == VIRTUALIZATION_VM && streq(parameter, "vm"))
-                return true;
+        if (v == VIRTUALIZATION_VM && streq(c->parameter, "vm"))
+                return !c->negate;
 
-        if (v == VIRTUALIZATION_CONTAINER && streq(parameter, "container"))
-                return true;
+        if (v == VIRTUALIZATION_CONTAINER && streq(c->parameter, "container"))
+                return !c->negate;
 
         /* Finally compare id */
-        return v > 0 && streq(parameter, id);
+        return (v > 0 && streq(c->parameter, id)) == !c->negate;
 }
 
-static bool test_security(const char *parameter) {
-        if (streq(parameter, "selinux"))
-                return use_selinux();
-        if (streq(parameter, "apparmor"))
-                return use_apparmor();
-        if (streq(parameter, "ima"))
-                return use_ima();
-        if (streq(parameter, "smack"))
-                return use_smack();
-        return false;
+static bool condition_test_security(Condition *c) {
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_SECURITY);
+
+        if (streq(c->parameter, "selinux"))
+                return use_selinux() == !c->negate;
+        if (streq(c->parameter, "apparmor"))
+                return use_apparmor() == !c->negate;
+        if (streq(c->parameter, "ima"))
+                return use_ima() == !c->negate;
+        if (streq(c->parameter, "smack"))
+                return use_smack() == !c->negate;
+        return c->negate;
 }
 
-static bool test_capability(const char *parameter) {
+static bool condition_test_capability(Condition *c) {
         cap_value_t value;
         FILE *f;
         char line[LINE_MAX];
         unsigned long long capabilities = (unsigned long long) -1;
 
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_CAPABILITY);
+
         /* If it's an invalid capability, we don't have it */
 
-        if (cap_from_name(parameter, &value) < 0)
-                return false;
+        if (cap_from_name(c->parameter, &value) < 0)
+                return c->negate;
 
         /* If it's a valid capability we default to assume
          * that we have it */
 
         f = fopen("/proc/self/status", "re");
         if (!f)
-                return true;
+                return !c->negate;
 
         while (fgets(line, sizeof(line), f)) {
                 truncate_nl(line);
@@ -196,42 +208,50 @@ static bool test_capability(const char *parameter) {
 
         fclose(f);
 
-        return !!(capabilities & (1ULL << value));
+        return !!(capabilities & (1ULL << value)) == !c->negate;
 }
 
-static bool test_host(const char *parameter) {
+static bool condition_test_host(Condition *c) {
         sd_id128_t x, y;
         char *h;
         int r;
         bool b;
 
-        if (sd_id128_from_string(parameter, &x) >= 0) {
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_HOST);
+
+        if (sd_id128_from_string(c->parameter, &x) >= 0) {
 
                 r = sd_id128_get_machine(&y);
                 if (r < 0)
-                        return false;
+                        return c->negate;
 
                 return sd_id128_equal(x, y);
         }
 
         h = gethostname_malloc();
         if (!h)
-                return false;
+                return c->negate;
 
-        b = fnmatch(parameter, h, FNM_CASEFOLD) == 0;
+        b = fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
         free(h);
 
-        return b;
+        return b == !c->negate;
 }
 
-static bool test_ac_power(const char *parameter) {
+static bool condition_test_ac_power(Condition *c) {
         int r;
 
-        r = parse_boolean(parameter);
+        assert(c);
+        assert(c->parameter);
+        assert(c->type == CONDITION_AC_POWER);
+
+        r = parse_boolean(c->parameter);
         if (r < 0)
-                return true;
+                return !c->negate;
 
-        return (on_ac_power() != 0) == !!r;
+        return ((on_ac_power() != 0) == !!r) == !c->negate;
 }
 
 static bool condition_test(Condition *c) {
@@ -293,22 +313,22 @@ static bool condition_test(Condition *c) {
         }
 
         case CONDITION_KERNEL_COMMAND_LINE:
-                return test_kernel_command_line(c->parameter) == !c->negate;
+                return condition_test_kernel_command_line(c);
 
         case CONDITION_VIRTUALIZATION:
-                return test_virtualization(c->parameter) == !c->negate;
+                return condition_test_virtualization(c);
 
         case CONDITION_SECURITY:
-                return test_security(c->parameter) == !c->negate;
+                return condition_test_security(c);
 
         case CONDITION_CAPABILITY:
-                return test_capability(c->parameter) == !c->negate;
+                return condition_test_capability(c);
 
         case CONDITION_HOST:
-                return test_host(c->parameter) == !c->negate;
+                return condition_test_host(c);
 
         case CONDITION_AC_POWER:
-                return test_ac_power(c->parameter) == !c->negate;
+                return condition_test_ac_power(c);
 
         case CONDITION_NULL:
                 return !c->negate;



More information about the systemd-commits mailing list