From 7e19cc54628bb320209ebab15b3b5d119fbccd00 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 Oct 2020 00:20:14 +0900 Subject: [PATCH] net-condition: move net_match_config() and related conf parsers --- src/libsystemd-network/network-internal.c | 396 --------------------- src/libsystemd-network/network-internal.h | 32 +- src/libsystemd-network/sd-dhcp6-client.c | 1 + src/network/netdev/netdev-gperf.gperf | 10 +- src/network/networkd-dhcp4.c | 2 +- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 4 +- src/network/test-networkd-conf.c | 7 +- src/shared/meson.build | 2 + src/shared/net-condition.c | 403 ++++++++++++++++++++++ src/shared/net-condition.h | 38 ++ src/udev/net/link-config-gperf.gperf | 2 +- src/udev/net/link-config.c | 1 + 13 files changed, 458 insertions(+), 442 deletions(-) create mode 100644 src/shared/net-condition.c create mode 100644 src/shared/net-condition.h 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 #include +#include #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 #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 + +#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 +#include + +#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"