summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-10-29 00:20:14 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2020-10-29 14:23:49 +0900
commit7e19cc54628bb320209ebab15b3b5d119fbccd00 (patch)
tree36965d2cfe9b72570939c4045b35bc8b6f481979
parent1929ed0e5897222422fc6e5c1d7b17ec9c1e36af (diff)
downloadsystemd-7e19cc54628bb320209ebab15b3b5d119fbccd00.tar.gz
net-condition: move net_match_config() and related conf parsers
-rw-r--r--src/libsystemd-network/network-internal.c396
-rw-r--r--src/libsystemd-network/network-internal.h32
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c1
-rw-r--r--src/network/netdev/netdev-gperf.gperf10
-rw-r--r--src/network/networkd-dhcp4.c2
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c4
-rw-r--r--src/network/test-networkd-conf.c7
-rw-r--r--src/shared/meson.build2
-rw-r--r--src/shared/net-condition.c403
-rw-r--r--src/shared/net-condition.h38
-rw-r--r--src/udev/net/link-config-gperf.gperf2
-rw-r--r--src/udev/net/link-config.c1
13 files changed, 458 insertions, 442 deletions
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index cb6cff2a97..4abe7298be 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -8,21 +8,14 @@
#include "sd-ndisc.h"
#include "alloc-util.h"
-#include "condition.h"
-#include "conf-parser.h"
#include "device-util.h"
#include "dhcp-lease-internal.h"
-#include "env-util.h"
-#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "network-internal.h"
#include "network-util.h"
#include "parse-util.h"
#include "siphash24.h"
-#include "socket-util.h"
-#include "string-table.h"
-#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -75,395 +68,6 @@ int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_
return 0;
}
-static bool net_condition_test_strv(char * const *patterns, const char *string) {
- char * const *p;
- bool match = false, has_positive_rule = false;
-
- if (strv_isempty(patterns))
- return true;
-
- STRV_FOREACH(p, patterns) {
- const char *q = *p;
- bool invert;
-
- invert = *q == '!';
- q += invert;
-
- if (!invert)
- has_positive_rule = true;
-
- if (string && fnmatch(q, string, 0) == 0) {
- if (invert)
- return false;
- else
- match = true;
- }
- }
-
- return has_positive_rule ? match : true;
-}
-
-static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
- if (net_condition_test_strv(patterns, ifname))
- return true;
-
- char * const *p;
- STRV_FOREACH(p, alternative_names)
- if (net_condition_test_strv(patterns, *p))
- return true;
-
- return false;
-}
-
-static int net_condition_test_property(char * const *match_property, sd_device *device) {
- char * const *p;
-
- if (strv_isempty(match_property))
- return true;
-
- STRV_FOREACH(p, match_property) {
- _cleanup_free_ char *key = NULL;
- const char *val, *dev_val;
- bool invert, v;
-
- invert = **p == '!';
-
- val = strchr(*p + invert, '=');
- if (!val)
- return -EINVAL;
-
- key = strndup(*p + invert, val - *p - invert);
- if (!key)
- return -ENOMEM;
-
- val++;
-
- v = device &&
- sd_device_get_property_value(device, key, &dev_val) >= 0 &&
- fnmatch(val, dev_val, 0) == 0;
-
- if (invert ? v : !v)
- return false;
- }
-
- return true;
-}
-
-static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
- [NL80211_IFTYPE_ADHOC] = "ad-hoc",
- [NL80211_IFTYPE_STATION] = "station",
- [NL80211_IFTYPE_AP] = "ap",
- [NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
- [NL80211_IFTYPE_WDS] = "wds",
- [NL80211_IFTYPE_MONITOR] = "monitor",
- [NL80211_IFTYPE_MESH_POINT] = "mesh-point",
- [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
- [NL80211_IFTYPE_P2P_GO] = "p2p-go",
- [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
- [NL80211_IFTYPE_OCB] = "ocb",
- [NL80211_IFTYPE_NAN] = "nan",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
-
-bool net_match_config(Set *match_mac,
- Set *match_permanent_mac,
- char * const *match_paths,
- char * const *match_drivers,
- char * const *match_iftypes,
- char * const *match_names,
- char * const *match_property,
- char * const *match_wifi_iftype,
- char * const *match_ssid,
- Set *match_bssid,
- sd_device *device,
- const struct ether_addr *dev_mac,
- const struct ether_addr *dev_permanent_mac,
- const char *dev_driver,
- unsigned short dev_iftype,
- const char *dev_name,
- char * const *alternative_names,
- enum nl80211_iftype dev_wifi_iftype,
- const char *dev_ssid,
- const struct ether_addr *dev_bssid) {
-
- _cleanup_free_ char *dev_iftype_str;
- const char *dev_path = NULL;
-
- dev_iftype_str = link_get_type_string(device, dev_iftype);
-
- if (device) {
- const char *mac_str;
-
- (void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
- if (!dev_driver)
- (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
- if (!dev_name)
- (void) sd_device_get_sysname(device, &dev_name);
- if (!dev_mac &&
- sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
- dev_mac = ether_aton(mac_str);
- }
-
- if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
- return false;
-
- if (match_permanent_mac &&
- (!dev_permanent_mac ||
- ether_addr_is_null(dev_permanent_mac) ||
- !set_contains(match_permanent_mac, dev_permanent_mac)))
- return false;
-
- if (!net_condition_test_strv(match_paths, dev_path))
- return false;
-
- if (!net_condition_test_strv(match_drivers, dev_driver))
- return false;
-
- if (!net_condition_test_strv(match_iftypes, dev_iftype_str))
- return false;
-
- if (!net_condition_test_ifname(match_names, dev_name, alternative_names))
- return false;
-
- if (!net_condition_test_property(match_property, device))
- return false;
-
- if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(dev_wifi_iftype)))
- return false;
-
- if (!net_condition_test_strv(match_ssid, dev_ssid))
- return false;
-
- if (match_bssid && (!dev_bssid || !set_contains(match_bssid, dev_bssid)))
- return false;
-
- return true;
-}
-
-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 **list = data, *c;
- bool negate;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- *list = condition_free_list_type(*list, cond);
- return 0;
- }
-
- negate = rvalue[0] == '!';
- if (negate)
- rvalue++;
-
- c = condition_new(cond, rvalue, false, negate);
- if (!c)
- return log_oom();
-
- /* Drop previous assignment. */
- *list = condition_free_list_type(*list, cond);
-
- LIST_PREPEND(conditions, *list, c);
- return 0;
-}
-
-int config_parse_match_strv(
- 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) {
-
- const char *p = rvalue;
- char ***sv = data;
- bool invert;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- *sv = strv_free(*sv);
- return 0;
- }
-
- invert = *p == '!';
- p += invert;
-
- for (;;) {
- _cleanup_free_ char *word = NULL, *k = NULL;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
- if (r == 0)
- return 0;
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Invalid syntax, ignoring: %s", rvalue);
- return 0;
- }
-
- if (invert) {
- k = strjoin("!", word);
- if (!k)
- return log_oom();
- } else
- k = TAKE_PTR(word);
-
- r = strv_consume(sv, TAKE_PTR(k));
- if (r < 0)
- return log_oom();
- }
-}
-
-int config_parse_match_ifnames(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- const char *p = rvalue;
- char ***sv = data;
- bool invert;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- *sv = strv_free(*sv);
- return 0;
- }
-
- invert = *p == '!';
- p += invert;
-
- for (;;) {
- _cleanup_free_ char *word = NULL, *k = NULL;
-
- r = extract_first_word(&p, &word, NULL, 0);
- if (r == 0)
- return 0;
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Failed to parse interface name list: %s", rvalue);
- return 0;
- }
-
- if (!ifname_valid_full(word, ltype)) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Interface name is not valid or too long, ignoring assignment: %s", word);
- continue;
- }
-
- if (invert) {
- k = strjoin("!", word);
- if (!k)
- return log_oom();
- } else
- k = TAKE_PTR(word);
-
- r = strv_consume(sv, TAKE_PTR(k));
- if (r < 0)
- return log_oom();
- }
-}
-
-int config_parse_match_property(
- 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) {
-
- const char *p = rvalue;
- char ***sv = data;
- bool invert;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- *sv = strv_free(*sv);
- return 0;
- }
-
- invert = *p == '!';
- p += invert;
-
- for (;;) {
- _cleanup_free_ char *word = NULL, *k = NULL;
-
- r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
- if (r == 0)
- return 0;
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid syntax, ignoring: %s", rvalue);
- return 0;
- }
-
- if (!env_assignment_is_valid(word)) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid property or value, ignoring assignment: %s", word);
- continue;
- }
-
- if (invert) {
- k = strjoin("!", word);
- if (!k)
- return log_oom();
- } else
- k = TAKE_PTR(word);
-
- r = strv_consume(sv, TAKE_PTR(k));
- if (r < 0)
- return log_oom();
- }
-}
-
size_t serialize_in_addrs(FILE *f,
const struct in_addr *addresses,
size_t size,
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 90fd2fb2aa..8bdaa29c78 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -1,42 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#include <linux/nl80211.h>
#include <stdbool.h>
+#include <stdio.h>
#include "sd-device.h"
#include "sd-dhcp-lease.h"
-#include "conf-parser.h"
-#include "set.h"
-#include "strv.h"
-
-bool net_match_config(Set *match_mac,
- Set *match_permanent_mac,
- char * const *match_paths,
- char * const *match_drivers,
- char * const *match_iftypes,
- char * const *match_names,
- char * const *match_property,
- char * const *match_wifi_iftype,
- char * const *match_ssid,
- Set *match_bssid,
- sd_device *device,
- const struct ether_addr *dev_mac,
- const struct ether_addr *dev_permanent_mac,
- const char *dev_driver,
- unsigned short dev_iftype,
- const char *dev_name,
- char * const *alternative_names,
- enum nl80211_iftype dev_wifi_iftype,
- const char *dev_ssid,
- const struct ether_addr *dev_bssid);
-
-CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
-CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
-CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
-CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
-
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result);
const char *net_get_name_persistent(sd_device *device);
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 6d27c4685e..43d42b4f86 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -25,6 +25,7 @@
#include "random-util.h"
#include "socket-util.h"
#include "string-table.h"
+#include "strv.h"
#include "util.h"
#include "web-util.h"
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 4e89761f2c..35cd01ef0d 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -7,23 +7,23 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "bond.h"
#include "bridge.h"
#include "conf-parser.h"
+#include "fou-tunnel.h"
#include "geneve.h"
#include "ipvlan.h"
+#include "l2tp-tunnel.h"
#include "macsec.h"
#include "macvlan.h"
+#include "net-condition.h"
+#include "netdev.h"
#include "tunnel.h"
#include "tuntap.h"
#include "veth.h"
#include "vlan-util.h"
#include "vlan.h"
-#include "vxlan.h"
#include "vrf.h"
-#include "netdev.h"
-#include "network-internal.h"
#include "vxcan.h"
+#include "vxlan.h"
#include "wireguard.h"
-#include "fou-tunnel.h"
-#include "l2tp-tunnel.h"
#include "xfrm.h"
%}
struct ConfigPerfItem;
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index bb8c34f7cc..89bc15bb87 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -17,7 +17,7 @@
#include "networkd-manager.h"
#include "networkd-network.h"
#include "string-table.h"
-#include "string-util.h"
+#include "strv.h"
#include "sysctl-util.h"
#include "web-util.h"
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 5cc9e3e8f6..19c3b088a1 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -5,7 +5,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include <stddef.h>
#include "conf-parser.h"
#include "netem.h"
-#include "network-internal.h"
+#include "net-condition.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-can.h"
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 426dd0a8f0..dd937d37f2 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -12,11 +12,11 @@
#include "fd-util.h"
#include "hostname-util.h"
#include "in-addr-util.h"
-#include "networkd-dhcp-server.h"
-#include "network-internal.h"
+#include "net-condition.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-dhcp-common.h"
+#include "networkd-dhcp-server.h"
#include "networkd-fdb.h"
#include "networkd-manager.h"
#include "networkd-mdb.h"
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index 030e50688a..57c5068e3a 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -1,15 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "macro.h"
-#include "set.h"
-#include "string-util.h"
-
-#include "network-internal.h"
+#include "net-condition.h"
#include "networkd-conf.h"
#include "networkd-network.h"
+#include "strv.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) {
DUID actual = {};
diff --git a/src/shared/meson.build b/src/shared/meson.build
index 260ee5a8b6..aa3c915f33 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -169,6 +169,8 @@ shared_sources = files('''
module-util.h
mount-util.c
mount-util.h
+ net-condition.c
+ net-condition.h
netif-naming-scheme.c
netif-naming-scheme.h
nscd-flush.c
diff --git a/src/shared/net-condition.c b/src/shared/net-condition.c
new file mode 100644
index 0000000000..b3bcebff1b
--- /dev/null
+++ b/src/shared/net-condition.c
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <netinet/ether.h>
+
+#include "condition.h"
+#include "env-util.h"
+#include "log.h"
+#include "net-condition.h"
+#include "network-util.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "strv.h"
+
+static bool net_condition_test_strv(char * const *patterns, const char *string) {
+ char * const *p;
+ bool match = false, has_positive_rule = false;
+
+ if (strv_isempty(patterns))
+ return true;
+
+ STRV_FOREACH(p, patterns) {
+ const char *q = *p;
+ bool invert;
+
+ invert = *q == '!';
+ q += invert;
+
+ if (!invert)
+ has_positive_rule = true;
+
+ if (string && fnmatch(q, string, 0) == 0) {
+ if (invert)
+ return false;
+ else
+ match = true;
+ }
+ }
+
+ return has_positive_rule ? match : true;
+}
+
+static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
+ if (net_condition_test_strv(patterns, ifname))
+ return true;
+
+ char * const *p;
+ STRV_FOREACH(p, alternative_names)
+ if (net_condition_test_strv(patterns, *p))
+ return true;
+
+ return false;
+}
+
+static int net_condition_test_property(char * const *match_property, sd_device *device) {
+ char * const *p;
+
+ if (strv_isempty(match_property))
+ return true;
+
+ STRV_FOREACH(p, match_property) {
+ _cleanup_free_ char *key = NULL;
+ const char *val, *dev_val;
+ bool invert, v;
+
+ invert = **p == '!';
+
+ val = strchr(*p + invert, '=');
+ if (!val)
+ return -EINVAL;
+
+ key = strndup(*p + invert, val - *p - invert);
+ if (!key)
+ return -ENOMEM;
+
+ val++;
+
+ v = device &&
+ sd_device_get_property_value(device, key, &dev_val) >= 0 &&
+ fnmatch(val, dev_val, 0) == 0;
+
+ if (invert ? v : !v)
+ return false;
+ }
+
+ return true;
+}
+
+static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = {
+ [NL80211_IFTYPE_ADHOC] = "ad-hoc",
+ [NL80211_IFTYPE_STATION] = "station",
+ [NL80211_IFTYPE_AP] = "ap",
+ [NL80211_IFTYPE_AP_VLAN] = "ap-vlan",
+ [NL80211_IFTYPE_WDS] = "wds",
+ [NL80211_IFTYPE_MONITOR] = "monitor",
+ [NL80211_IFTYPE_MESH_POINT] = "mesh-point",
+ [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client",
+ [NL80211_IFTYPE_P2P_GO] = "p2p-go",
+ [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device",
+ [NL80211_IFTYPE_OCB] = "ocb",
+ [NL80211_IFTYPE_NAN] = "nan",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype);
+
+bool net_match_config(
+ Set *match_mac,
+ Set *match_permanent_mac,
+ char * const *match_paths,
+ char * const *match_drivers,
+ char * const *match_iftypes,
+ char * const *match_names,
+ char * const *match_property,
+ char * const *match_wifi_iftype,
+ char * const *match_ssid,
+ Set *match_bssid,
+ sd_device *device,
+ const struct ether_addr *dev_mac,
+ const struct ether_addr *dev_permanent_mac,
+ const char *dev_driver,
+ unsigned short dev_iftype,
+ const char *dev_name,
+ char * const *alternative_names,
+ enum nl80211_iftype dev_wifi_iftype,
+ const char *dev_ssid,
+ const struct ether_addr *dev_bssid) {
+
+ _cleanup_free_ char *dev_iftype_str;
+ const char *dev_path = NULL;
+
+ dev_iftype_str = link_get_type_string(device, dev_iftype);
+
+ if (device) {
+ const char *mac_str;
+
+ (void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
+ if (!dev_driver)
+ (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
+ if (!dev_name)
+ (void) sd_device_get_sysname(device, &dev_name);
+ if (!dev_mac &&
+ sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
+ dev_mac = ether_aton(mac_str);
+ }
+
+ if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
+ return false;
+
+ if (match_permanent_mac &&
+ (!dev_permanent_mac ||
+ ether_addr_is_null(dev_permanent_mac) ||
+ !set_contains(match_permanent_mac, dev_permanent_mac)))
+ return false;
+
+ if (!net_condition_test_strv(match_paths, dev_path))
+ return false;
+
+ if (!net_condition_test_strv(match_drivers, dev_driver))
+ return false;
+
+ if (!net_condition_test_strv(match_iftypes, dev_iftype_str))
+ return false;
+
+ if (!net_condition_test_ifname(match_names, dev_name, alternative_names))
+ return false;
+
+ if (!net_condition_test_property(match_property, device))
+ return false;
+
+ if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(dev_wifi_iftype)))
+ return false;
+
+ if (!net_condition_test_strv(match_ssid, dev_ssid))
+ return false;
+
+ if (match_bssid && (!dev_bssid || !set_contains(match_bssid, dev_bssid)))
+ return false;
+
+ return true;
+}
+
+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 **list = data, *c;
+ bool negate;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *list = condition_free_list_type(*list, cond);
+ return 0;
+ }
+
+ negate = rvalue[0] == '!';
+ if (negate)
+ rvalue++;
+
+ c = condition_new(cond, rvalue, false, negate);
+ if (!c)
+ return log_oom();
+
+ /* Drop previous assignment. */
+ *list = condition_free_list_type(*list, cond);
+
+ LIST_PREPEND(conditions, *list, c);
+ return 0;
+}
+
+int config_parse_match_strv(
+ 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) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *sv = strv_free(*sv);
+ return 0;
+ }
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
+}
+
+int config_parse_match_ifnames(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *sv = strv_free(*sv);
+ return 0;
+ }
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to parse interface name list, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!ifname_valid_full(word, ltype)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Interface name is not valid or too long, ignoring assignment: %s", word);
+ continue;
+ }
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
+}
+
+int config_parse_match_property(
+ 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) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *sv = strv_free(*sv);
+ return 0;
+ }
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!env_assignment_is_valid(word)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid property or value, ignoring assignment: %s", word);
+ continue;
+ }
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
+}
diff --git a/src/shared/net-condition.h b/src/shared/net-condition.h
new file mode 100644
index 0000000000..31d5d01aa6
--- /dev/null
+++ b/src/shared/net-condition.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <linux/nl80211.h>
+#include <stdbool.h>
+
+#include "sd-device.h"
+
+#include "conf-parser.h"
+#include "ether-addr-util.h"
+#include "set.h"
+
+bool net_match_config(
+ Set *match_mac,
+ Set *match_permanent_mac,
+ char * const *match_paths,
+ char * const *match_drivers,
+ char * const *match_iftypes,
+ char * const *match_names,
+ char * const *match_property,
+ char * const *match_wifi_iftype,
+ char * const *match_ssid,
+ Set *match_bssid,
+ sd_device *device,
+ const struct ether_addr *dev_mac,
+ const struct ether_addr *dev_permanent_mac,
+ const char *dev_driver,
+ unsigned short dev_iftype,
+ const char *dev_name,
+ char * const *alternative_names,
+ enum nl80211_iftype dev_wifi_iftype,
+ const char *dev_ssid,
+ const struct ether_addr *dev_bssid);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf
index 20f5d7e5a4..6c8d574875 100644
--- a/src/udev/net/link-config-gperf.gperf
+++ b/src/udev/net/link-config-gperf.gperf
@@ -6,7 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "conf-parser.h"
#include "ethtool-util.h"
#include "link-config.h"
-#include "network-internal.h"
+#include "net-condition.h"
#include "socket-util.h"
%}
struct ConfigPerfItem;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index fe542ca8a5..c0b74ed3d4 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -18,6 +18,7 @@
#include "link-config.h"
#include "log.h"
#include "memory-util.h"
+#include "net-condition.h"
#include "netif-naming-scheme.h"
#include "netlink-util.h"
#include "network-internal.h"