• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14895667988

07 May 2025 08:57PM UTC coverage: 72.225% (-0.007%) from 72.232%
14895667988

push

github

yuwata
network: log_link_message_debug_errno() automatically append %m if necessary

Follow-up for d28746ef5.
Fixes CID#1609753.

0 of 1 new or added line in 1 file covered. (0.0%)

20297 existing lines in 338 files now uncovered.

297407 of 411780 relevant lines covered (72.22%)

695716.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.14
/src/shared/net-condition.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <fnmatch.h>
4
#include <netinet/ether.h>
5

6
#include "alloc-util.h"
7
#include "condition.h"
8
#include "env-util.h"
9
#include "log.h"
10
#include "net-condition.h"
11
#include "netif-util.h"
12
#include "network-util.h"
13
#include "socket-util.h"
14
#include "string-table.h"
15
#include "strv.h"
16
#include "wifi-util.h"
17

18
void net_match_clear(NetMatch *match) {
7,547✔
19
        if (!match)
7,547✔
20
                return;
21

22
        match->hw_addr = set_free(match->hw_addr);
7,547✔
23
        match->permanent_hw_addr = set_free(match->permanent_hw_addr);
7,547✔
24
        match->path = strv_free(match->path);
7,547✔
25
        match->driver = strv_free(match->driver);
7,547✔
26
        match->iftype = strv_free(match->iftype);
7,547✔
27
        match->kind = strv_free(match->kind);
7,547✔
28
        match->ifname = strv_free(match->ifname);
7,547✔
29
        match->property = strv_free(match->property);
7,547✔
30
        match->wlan_iftype = strv_free(match->wlan_iftype);
7,547✔
31
        match->ssid = strv_free(match->ssid);
7,547✔
32
        match->bssid = set_free(match->bssid);
7,547✔
33
}
34

35
bool net_match_is_empty(const NetMatch *match) {
7,547✔
36
        assert(match);
7,547✔
37

38
        return
7,547✔
39
                set_isempty(match->hw_addr) &&
7,547✔
40
                set_isempty(match->permanent_hw_addr) &&
7,530✔
41
                strv_isempty(match->path) &&
7,530✔
42
                strv_isempty(match->driver) &&
7,530✔
43
                strv_isempty(match->iftype) &&
7,523✔
44
                strv_isempty(match->kind) &&
6,967✔
45
                strv_isempty(match->ifname) &&
1,564✔
UNCOV
46
                strv_isempty(match->property) &&
×
47
                strv_isempty(match->wlan_iftype) &&
×
48
                strv_isempty(match->ssid) &&
7,547✔
UNCOV
49
                set_isempty(match->bssid);
×
50
}
51

52
static bool net_condition_test_strv(char * const *patterns, const char *string) {
100,480✔
53
        bool match = false, has_positive_rule = false;
100,480✔
54

55
        if (strv_isempty(patterns))
100,480✔
56
                return true;
57

58
        STRV_FOREACH(p, patterns) {
89,269✔
59
                const char *q = *p;
67,600✔
60
                bool invert;
67,600✔
61

62
                invert = *q == '!';
67,600✔
63
                q += invert;
67,600✔
64

65
                if (!invert)
67,600✔
66
                        has_positive_rule = true;
67,600✔
67

68
                if (string && fnmatch(q, string, 0) == 0) {
67,600✔
69
                        if (invert)
5,033✔
70
                                return false;
71
                        else
72
                                match = true;
73
                }
74
        }
75

76
        return has_positive_rule ? match : true;
21,669✔
77
}
78

79
static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
9,765✔
80
        if (net_condition_test_strv(patterns, ifname))
9,765✔
81
                return true;
82

83
        STRV_FOREACH(p, alternative_names)
5,688✔
84
                if (net_condition_test_strv(patterns, *p))
216✔
85
                        return true;
86

87
        return false;
88
}
89

90
static int net_condition_test_property(char * const *match_property, sd_device *device) {
4,293✔
91
        if (strv_isempty(match_property))
4,297✔
92
                return true;
93

94
        STRV_FOREACH(p, match_property) {
6✔
95
                _cleanup_free_ char *key = NULL;
4✔
96
                const char *val, *dev_val;
4✔
97
                bool invert, v;
4✔
98

99
                invert = **p == '!';
4✔
100

101
                val = strchr(*p + invert, '=');
4✔
102
                if (!val)
4✔
103
                        return -EINVAL;
104

105
                key = strndup(*p + invert, val - *p - invert);
4✔
106
                if (!key)
4✔
107
                        return -ENOMEM;
108

109
                val++;
4✔
110

111
                v = device &&
4✔
112
                        sd_device_get_property_value(device, key, &dev_val) >= 0 &&
8✔
113
                        fnmatch(val, dev_val, 0) == 0;
4✔
114

115
                if (invert ? v : !v)
4✔
116
                        return false;
117
        }
118

119
        return true;
120
}
121

122
int net_match_config(
20,722✔
123
                const NetMatch *match,
124
                sd_device *device,
125
                const struct hw_addr_data *hw_addr,
126
                const struct hw_addr_data *permanent_hw_addr,
127
                const char *driver,
128
                unsigned short iftype,
129
                const char *kind,
130
                const char *ifname,
131
                char * const *alternative_names,
132
                enum nl80211_iftype wlan_iftype,
133
                const char *ssid,
134
                const struct ether_addr *bssid) {
135

136
        _cleanup_free_ char *iftype_str = NULL;
20,722✔
137
        const char *path = NULL;
20,722✔
138

139
        assert(match);
20,722✔
140

141
        if (net_get_type_string(device, iftype, &iftype_str) == -ENOMEM)
20,722✔
142
                return -ENOMEM;
143

144
        if (device)
20,722✔
145
                (void) sd_device_get_property_value(device, "ID_PATH", &path);
19,934✔
146

147
        if (match->hw_addr && (!hw_addr || !set_contains(match->hw_addr, hw_addr)))
20,722✔
148
                return false;
9✔
149

150
        if (match->permanent_hw_addr &&
20,713✔
151
            (!permanent_hw_addr ||
×
UNCOV
152
             !set_contains(match->permanent_hw_addr, permanent_hw_addr)))
×
UNCOV
153
                return false;
×
154

155
        if (!net_condition_test_strv(match->path, path))
20,713✔
156
                return false;
157

158
        if (!net_condition_test_strv(match->driver, driver))
20,713✔
159
                return false;
160

161
        if (!net_condition_test_strv(match->iftype, iftype_str))
20,713✔
162
                return false;
163

164
        if (!net_condition_test_strv(match->kind, kind))
19,778✔
165
                return false;
166

167
        if (!net_condition_test_ifname(match->ifname, ifname, alternative_names))
9,765✔
168
                return false;
169

170
        if (!net_condition_test_property(match->property, device))
4,293✔
171
                return false;
172

173
        if (!net_condition_test_strv(match->wlan_iftype, nl80211_iftype_to_string(wlan_iftype)))
4,291✔
174
                return false;
175

176
        if (!net_condition_test_strv(match->ssid, ssid))
4,291✔
177
                return false;
178

179
        if (match->bssid && (!bssid || !set_contains(match->bssid, bssid)))
4,291✔
UNCOV
180
                return false;
×
181

182
        return true;
183
}
184

185
int config_parse_net_condition(
1,108✔
186
                const char *unit,
187
                const char *filename,
188
                unsigned line,
189
                const char *section,
190
                unsigned section_line,
191
                const char *lvalue,
192
                int ltype,
193
                const char *rvalue,
194
                void *data,
195
                void *userdata) {
196

197
        ConditionType cond = ltype;
1,108✔
198
        Condition **list = data, *c;
1,108✔
199
        bool negate;
1,108✔
200

201
        assert(filename);
1,108✔
202
        assert(lvalue);
1,108✔
203
        assert(rvalue);
1,108✔
204
        assert(data);
1,108✔
205

206
        if (isempty(rvalue)) {
1,108✔
UNCOV
207
                *list = condition_free_list_type(*list, cond);
×
UNCOV
208
                return 0;
×
209
        }
210

211
        negate = rvalue[0] == '!';
1,108✔
212
        if (negate)
1,108✔
UNCOV
213
                rvalue++;
×
214

215
        c = condition_new(cond, rvalue, false, negate);
1,108✔
216
        if (!c)
1,108✔
UNCOV
217
                return log_oom();
×
218

219
        /* Drop previous assignment. */
220
        *list = condition_free_list_type(*list, cond);
1,108✔
221

222
        LIST_PREPEND(conditions, *list, c);
1,108✔
223
        return 0;
1,108✔
224
}
225

226
int config_parse_match_strv(
6,540✔
227
                const char *unit,
228
                const char *filename,
229
                unsigned line,
230
                const char *section,
231
                unsigned section_line,
232
                const char *lvalue,
233
                int ltype,
234
                const char *rvalue,
235
                void *data,
236
                void *userdata) {
237

238
        const char *p = ASSERT_PTR(rvalue);
6,540✔
239
        char ***sv = ASSERT_PTR(data);
6,540✔
240
        bool invert;
6,540✔
241
        int r;
6,540✔
242

243
        assert(filename);
6,540✔
244
        assert(lvalue);
6,540✔
245

246
        if (isempty(rvalue)) {
6,540✔
UNCOV
247
                *sv = strv_free(*sv);
×
248
                return 0;
6,540✔
249
        }
250

251
        invert = *p == '!';
6,540✔
252
        p += invert;
6,540✔
253

254
        for (;;) {
6,544✔
255
                _cleanup_free_ char *word = NULL, *k = NULL;
13,084✔
256

257
                r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
13,084✔
258
                if (r == 0)
13,084✔
259
                        return 0;
260
                if (r == -ENOMEM)
6,544✔
261
                        return log_oom();
×
262
                if (r < 0) {
6,544✔
263
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
264
                                   "Invalid syntax, ignoring: %s", rvalue);
UNCOV
265
                        return 0;
×
266
                }
267

268
                if (invert) {
6,544✔
269
                        k = strjoin("!", word);
4✔
270
                        if (!k)
4✔
UNCOV
271
                                return log_oom();
×
272
                } else
273
                        k = TAKE_PTR(word);
6,540✔
274

275
                r = strv_consume(sv, TAKE_PTR(k));
6,544✔
276
                if (r < 0)
6,544✔
UNCOV
277
                        return log_oom();
×
278
        }
279
}
280

281
int config_parse_match_ifnames(
12,391✔
282
                const char *unit,
283
                const char *filename,
284
                unsigned line,
285
                const char *section,
286
                unsigned section_line,
287
                const char *lvalue,
288
                int ltype,
289
                const char *rvalue,
290
                void *data,
291
                void *userdata) {
292

293
        const char *p = ASSERT_PTR(rvalue);
12,391✔
294
        char ***sv = ASSERT_PTR(data);
12,391✔
295
        bool invert;
12,391✔
296
        int r;
12,391✔
297

298
        assert(filename);
12,391✔
299
        assert(lvalue);
12,391✔
300

301
        if (isempty(rvalue)) {
12,391✔
UNCOV
302
                *sv = strv_free(*sv);
×
303
                return 0;
12,391✔
304
        }
305

306
        invert = *p == '!';
12,391✔
307
        p += invert;
12,391✔
308

309
        for (;;) {
25,012✔
310
                _cleanup_free_ char *word = NULL, *k = NULL;
25,012✔
311

312
                r = extract_first_word(&p, &word, NULL, 0);
25,012✔
313
                if (r == 0)
25,012✔
314
                        return 0;
315
                if (r == -ENOMEM)
12,621✔
316
                        return log_oom();
×
317
                if (r < 0) {
12,621✔
318
                        log_syntax(unit, LOG_WARNING, filename, line, 0,
×
319
                                   "Failed to parse interface name list, ignoring: %s", rvalue);
UNCOV
320
                        return 0;
×
321
                }
322

323
                if (!ifname_valid_full(word, ltype)) {
12,621✔
324
                        log_syntax(unit, LOG_WARNING, filename, line, 0,
×
325
                                   "Interface name is not valid or too long, ignoring assignment: %s", word);
UNCOV
326
                        continue;
×
327
                }
328

329
                if (invert) {
12,621✔
330
                        k = strjoin("!", word);
4✔
331
                        if (!k)
4✔
UNCOV
332
                                return log_oom();
×
333
                } else
334
                        k = TAKE_PTR(word);
12,617✔
335

336
                r = strv_consume(sv, TAKE_PTR(k));
12,621✔
337
                if (r < 0)
12,621✔
UNCOV
338
                        return log_oom();
×
339
        }
340
}
341

342
int config_parse_match_property(
2✔
343
                const char *unit,
344
                const char *filename,
345
                unsigned line,
346
                const char *section,
347
                unsigned section_line,
348
                const char *lvalue,
349
                int ltype,
350
                const char *rvalue,
351
                void *data,
352
                void *userdata) {
353

354
        const char *p = ASSERT_PTR(rvalue);
2✔
355
        char ***sv = ASSERT_PTR(data);
2✔
356
        bool invert;
2✔
357
        int r;
2✔
358

359
        assert(filename);
2✔
360
        assert(lvalue);
2✔
361

362
        if (isempty(rvalue)) {
2✔
UNCOV
363
                *sv = strv_free(*sv);
×
364
                return 0;
2✔
365
        }
366

367
        invert = *p == '!';
2✔
368
        p += invert;
2✔
369

370
        for (;;) {
4✔
371
                _cleanup_free_ char *word = NULL, *k = NULL;
4✔
372

373
                r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
4✔
374
                if (r == 0)
4✔
375
                        return 0;
376
                if (r == -ENOMEM)
2✔
377
                        return log_oom();
×
378
                if (r < 0) {
2✔
379
                        log_syntax(unit, LOG_WARNING, filename, line, 0,
×
380
                                   "Invalid syntax, ignoring: %s", rvalue);
UNCOV
381
                        return 0;
×
382
                }
383

384
                if (!env_assignment_is_valid(word)) {
2✔
385
                        log_syntax(unit, LOG_WARNING, filename, line, 0,
×
386
                                   "Invalid property or value, ignoring assignment: %s", word);
UNCOV
387
                        continue;
×
388
                }
389

390
                if (invert) {
2✔
391
                        k = strjoin("!", word);
×
UNCOV
392
                        if (!k)
×
UNCOV
393
                                return log_oom();
×
394
                } else
395
                        k = TAKE_PTR(word);
2✔
396

397
                r = strv_consume(sv, TAKE_PTR(k));
2✔
398
                if (r < 0)
2✔
UNCOV
399
                        return log_oom();
×
400
        }
401
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc