1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/ether.h>
8 #include "net-condition.h"
9 #include "netif-util.h"
10 #include "network-util.h"
11 #include "socket-util.h"
12 #include "string-table.h"
14 #include "wifi-util.h"
16 void net_match_clear(NetMatch
*match
) {
20 match
->hw_addr
= set_free(match
->hw_addr
);
21 match
->permanent_hw_addr
= set_free(match
->permanent_hw_addr
);
22 match
->path
= strv_free(match
->path
);
23 match
->driver
= strv_free(match
->driver
);
24 match
->iftype
= strv_free(match
->iftype
);
25 match
->kind
= strv_free(match
->kind
);
26 match
->ifname
= strv_free(match
->ifname
);
27 match
->property
= strv_free(match
->property
);
28 match
->wlan_iftype
= strv_free(match
->wlan_iftype
);
29 match
->ssid
= strv_free(match
->ssid
);
30 match
->bssid
= set_free(match
->bssid
);
33 bool net_match_is_empty(const NetMatch
*match
) {
37 set_isempty(match
->hw_addr
) &&
38 set_isempty(match
->permanent_hw_addr
) &&
39 strv_isempty(match
->path
) &&
40 strv_isempty(match
->driver
) &&
41 strv_isempty(match
->iftype
) &&
42 strv_isempty(match
->kind
) &&
43 strv_isempty(match
->ifname
) &&
44 strv_isempty(match
->property
) &&
45 strv_isempty(match
->wlan_iftype
) &&
46 strv_isempty(match
->ssid
) &&
47 set_isempty(match
->bssid
);
50 static bool net_condition_test_strv(char * const *patterns
, const char *string
) {
52 bool match
= false, has_positive_rule
= false;
54 if (strv_isempty(patterns
))
57 STRV_FOREACH(p
, patterns
) {
65 has_positive_rule
= true;
67 if (string
&& fnmatch(q
, string
, 0) == 0) {
75 return has_positive_rule
? match
: true;
78 static bool net_condition_test_ifname(char * const *patterns
, const char *ifname
, char * const *alternative_names
) {
79 if (net_condition_test_strv(patterns
, ifname
))
83 STRV_FOREACH(p
, alternative_names
)
84 if (net_condition_test_strv(patterns
, *p
))
90 static int net_condition_test_property(char * const *match_property
, sd_device
*device
) {
93 if (strv_isempty(match_property
))
96 STRV_FOREACH(p
, match_property
) {
97 _cleanup_free_
char *key
= NULL
;
98 const char *val
, *dev_val
;
103 val
= strchr(*p
+ invert
, '=');
107 key
= strndup(*p
+ invert
, val
- *p
- invert
);
114 sd_device_get_property_value(device
, key
, &dev_val
) >= 0 &&
115 fnmatch(val
, dev_val
, 0) == 0;
124 int net_match_config(
125 const NetMatch
*match
,
127 const struct hw_addr_data
*hw_addr
,
128 const struct hw_addr_data
*permanent_hw_addr
,
130 unsigned short iftype
,
133 char * const *alternative_names
,
134 enum nl80211_iftype wlan_iftype
,
136 const struct ether_addr
*bssid
) {
138 _cleanup_free_
char *iftype_str
= NULL
;
139 const char *path
= NULL
;
143 if (net_get_type_string(device
, iftype
, &iftype_str
) == -ENOMEM
)
147 (void) sd_device_get_property_value(device
, "ID_PATH", &path
);
149 if (match
->hw_addr
&& (!hw_addr
|| !set_contains(match
->hw_addr
, hw_addr
)))
152 if (match
->permanent_hw_addr
&&
153 (!permanent_hw_addr
||
154 !set_contains(match
->permanent_hw_addr
, permanent_hw_addr
)))
157 if (!net_condition_test_strv(match
->path
, path
))
160 if (!net_condition_test_strv(match
->driver
, driver
))
163 if (!net_condition_test_strv(match
->iftype
, iftype_str
))
166 if (!net_condition_test_strv(match
->kind
, kind
))
169 if (!net_condition_test_ifname(match
->ifname
, ifname
, alternative_names
))
172 if (!net_condition_test_property(match
->property
, device
))
175 if (!net_condition_test_strv(match
->wlan_iftype
, nl80211_iftype_to_string(wlan_iftype
)))
178 if (!net_condition_test_strv(match
->ssid
, ssid
))
181 if (match
->bssid
&& (!bssid
|| !set_contains(match
->bssid
, bssid
)))
187 int config_parse_net_condition(
189 const char *filename
,
192 unsigned section_line
,
199 ConditionType cond
= ltype
;
200 Condition
**list
= data
, *c
;
208 if (isempty(rvalue
)) {
209 *list
= condition_free_list_type(*list
, cond
);
213 negate
= rvalue
[0] == '!';
217 c
= condition_new(cond
, rvalue
, false, negate
);
221 /* Drop previous assignment. */
222 *list
= condition_free_list_type(*list
, cond
);
224 LIST_PREPEND(conditions
, *list
, c
);
228 int config_parse_match_strv(
230 const char *filename
,
233 unsigned section_line
,
240 const char *p
= rvalue
;
250 if (isempty(rvalue
)) {
251 *sv
= strv_free(*sv
);
259 _cleanup_free_
char *word
= NULL
, *k
= NULL
;
261 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_UNQUOTE
|EXTRACT_RETAIN_ESCAPE
);
267 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
268 "Invalid syntax, ignoring: %s", rvalue
);
273 k
= strjoin("!", word
);
279 r
= strv_consume(sv
, TAKE_PTR(k
));
285 int config_parse_match_ifnames(
287 const char *filename
,
290 unsigned section_line
,
297 const char *p
= rvalue
;
307 if (isempty(rvalue
)) {
308 *sv
= strv_free(*sv
);
316 _cleanup_free_
char *word
= NULL
, *k
= NULL
;
318 r
= extract_first_word(&p
, &word
, NULL
, 0);
324 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
325 "Failed to parse interface name list, ignoring: %s", rvalue
);
329 if (!ifname_valid_full(word
, ltype
)) {
330 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
331 "Interface name is not valid or too long, ignoring assignment: %s", word
);
336 k
= strjoin("!", word
);
342 r
= strv_consume(sv
, TAKE_PTR(k
));
348 int config_parse_match_property(
350 const char *filename
,
353 unsigned section_line
,
360 const char *p
= rvalue
;
370 if (isempty(rvalue
)) {
371 *sv
= strv_free(*sv
);
379 _cleanup_free_
char *word
= NULL
, *k
= NULL
;
381 r
= extract_first_word(&p
, &word
, NULL
, EXTRACT_CUNESCAPE
|EXTRACT_UNQUOTE
);
387 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
388 "Invalid syntax, ignoring: %s", rvalue
);
392 if (!env_assignment_is_valid(word
)) {
393 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
394 "Invalid property or value, ignoring assignment: %s", word
);
399 k
= strjoin("!", word
);
405 r
= strv_consume(sv
, TAKE_PTR(k
));