• 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

86.14
/src/network/netdev/macsec.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <linux/genetlink.h>
4
#include <linux/if_arp.h>
5
#include <linux/if_ether.h>
6
#include <linux/if_macsec.h>
7
#include <netinet/in.h>
8

9
#include "alloc-util.h"
10
#include "conf-parser.h"
11
#include "fileio.h"
12
#include "hashmap.h"
13
#include "hexdecoct.h"
14
#include "macsec.h"
15
#include "memory-util.h"
16
#include "netlink-util.h"
17
#include "networkd-manager.h"
18
#include "parse-helpers.h"
19
#include "parse-util.h"
20
#include "socket-util.h"
21
#include "string-table.h"
22
#include "string-util.h"
23
#include "unaligned.h"
24

25
#define SECURITY_ASSOCIATION_NULL               \
26
        (SecurityAssociation) {                 \
27
                .activate = -1,                 \
28
                .use_for_encoding = -1,         \
29
        }
30

31
static void security_association_clear(SecurityAssociation *sa) {
16✔
32
        if (!sa)
16✔
33
                return;
34

35
        explicit_bzero_safe(sa->key, sa->key_len);
16✔
36
        free(sa->key);
16✔
37
        free(sa->key_file);
16✔
38
}
39

40
static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c) {
12✔
41
        if (!c)
12✔
42
                return NULL;
43

44
        if (c->macsec && c->section)
12✔
45
                ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
12✔
46

47
        config_section_free(c->section);
12✔
48
        security_association_clear(&c->sa);
12✔
49

50
        return mfree(c);
12✔
51
}
52

53
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
148✔
54

55
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
10✔
56
                receive_association_hash_ops_by_section,
57
                ConfigSection, config_section_hash_func, config_section_compare_func,
58
                ReceiveAssociation, macsec_receive_association_free);
59

60
static int macsec_receive_association_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveAssociation **ret) {
64✔
61
        _cleanup_(config_section_freep) ConfigSection *n = NULL;
64✔
62
        _cleanup_(macsec_receive_association_freep) ReceiveAssociation *c = NULL;
64✔
63
        int r;
64✔
64

65
        assert(s);
64✔
66
        assert(ret);
64✔
67
        assert(filename);
64✔
68
        assert(section_line > 0);
64✔
69

70
        r = config_section_new(filename, section_line, &n);
64✔
71
        if (r < 0)
64✔
72
                return r;
73

74
        c = ordered_hashmap_get(s->receive_associations_by_section, n);
64✔
75
        if (c) {
64✔
76
                *ret = TAKE_PTR(c);
52✔
77
                return 0;
52✔
78
        }
79

80
        c = new(ReceiveAssociation, 1);
12✔
81
        if (!c)
12✔
82
                return -ENOMEM;
83

84
        *c = (ReceiveAssociation) {
12✔
85
                .macsec = s,
86
                .section = TAKE_PTR(n),
12✔
87
                .sa = SECURITY_ASSOCIATION_NULL,
88
        };
89

90
        r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &receive_association_hash_ops_by_section, c->section, c);
12✔
91
        if (r < 0)
12✔
92
                return r;
93

94
        *ret = TAKE_PTR(c);
12✔
95
        return 0;
12✔
96
}
97

98
static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
4✔
99
        if (!c)
4✔
100
                return NULL;
101

102
        if (c->macsec) {
4✔
103
                if (c->sci.as_uint64 > 0)
4✔
104
                        ordered_hashmap_remove_value(c->macsec->receive_channels, &c->sci.as_uint64, c);
4✔
105

106
                if (c->section)
4✔
107
                        ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section);
2✔
108
        }
109

110
        config_section_free(c->section);
4✔
111

112
        return mfree(c);
4✔
113
}
114

115
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
36✔
116

117
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
4✔
118
                receive_channel_hash_ops,
119
                uint64_t, uint64_hash_func, uint64_compare_func,
120
                ReceiveChannel, macsec_receive_channel_free);
121

UNCOV
122
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
×
123
                receive_channel_hash_ops_by_section,
124
                ConfigSection, config_section_hash_func, config_section_compare_func,
125
                ReceiveChannel, macsec_receive_channel_free);
126

127
static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) {
4✔
128
        ReceiveChannel *c;
4✔
129

130
        assert(s);
4✔
131

132
        c = new(ReceiveChannel, 1);
4✔
133
        if (!c)
4✔
134
                return -ENOMEM;
135

136
        *c = (ReceiveChannel) {
4✔
137
                .macsec = s,
138
                .sci.as_uint64 = sci,
139
        };
140

141
        *ret = c;
4✔
142
        return 0;
4✔
143
}
144

145
static int macsec_receive_channel_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveChannel **ret) {
4✔
146
        _cleanup_(config_section_freep) ConfigSection *n = NULL;
4✔
147
        _cleanup_(macsec_receive_channel_freep) ReceiveChannel *c = NULL;
4✔
148
        int r;
4✔
149

150
        assert(s);
4✔
151
        assert(ret);
4✔
152
        assert(filename);
4✔
153
        assert(section_line > 0);
4✔
154

155
        r = config_section_new(filename, section_line, &n);
4✔
156
        if (r < 0)
4✔
157
                return r;
158

159
        c = ordered_hashmap_get(s->receive_channels_by_section, n);
4✔
160
        if (c) {
4✔
161
                *ret = TAKE_PTR(c);
2✔
162
                return 0;
2✔
163
        }
164

165
        r = macsec_receive_channel_new(s, 0, &c);
2✔
166
        if (r < 0)
2✔
167
                return r;
168

169
        c->section = TAKE_PTR(n);
2✔
170

171
        r = ordered_hashmap_ensure_put(&s->receive_channels_by_section, &receive_channel_hash_ops_by_section, c->section, c);
2✔
172
        if (r < 0)
2✔
173
                return r;
174

175
        *ret = TAKE_PTR(c);
2✔
176
        return 0;
2✔
177
}
178

179
static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation *a) {
4✔
180
        if (!a)
4✔
181
                return NULL;
182

183
        if (a->macsec && a->section)
4✔
184
                ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
4✔
185

186
        config_section_free(a->section);
4✔
187
        security_association_clear(&a->sa);
4✔
188

189
        return mfree(a);
4✔
190
}
191

192
DEFINE_SECTION_CLEANUP_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
72✔
193

194
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
4✔
195
                transmit_association_hash_ops_by_section,
196
                ConfigSection, config_section_hash_func, config_section_compare_func,
197
                TransmitAssociation, macsec_transmit_association_free);
198

199
static int macsec_transmit_association_new_static(MACsec *s, const char *filename, unsigned section_line, TransmitAssociation **ret) {
16✔
200
        _cleanup_(config_section_freep) ConfigSection *n = NULL;
16✔
201
        _cleanup_(macsec_transmit_association_freep) TransmitAssociation *a = NULL;
16✔
202
        int r;
16✔
203

204
        assert(s);
16✔
205
        assert(ret);
16✔
206
        assert(filename);
16✔
207
        assert(section_line > 0);
16✔
208

209
        r = config_section_new(filename, section_line, &n);
16✔
210
        if (r < 0)
16✔
211
                return r;
212

213
        a = ordered_hashmap_get(s->transmit_associations_by_section, n);
16✔
214
        if (a) {
16✔
215
                *ret = TAKE_PTR(a);
12✔
216
                return 0;
12✔
217
        }
218

219
        a = new(TransmitAssociation, 1);
4✔
220
        if (!a)
4✔
221
                return -ENOMEM;
222

223
        *a = (TransmitAssociation) {
4✔
224
                .macsec = s,
225
                .section = TAKE_PTR(n),
4✔
226
                .sa = SECURITY_ASSOCIATION_NULL,
227
        };
228

229
        r = ordered_hashmap_ensure_put(&s->transmit_associations_by_section, &transmit_association_hash_ops_by_section, a->section, a);
4✔
230
        if (r < 0)
4✔
231
                return r;
232

233
        *ret = TAKE_PTR(a);
4✔
234
        return 0;
4✔
235
}
236

237
static int netdev_macsec_create_message(NetDev *netdev, int command, sd_netlink_message **ret) {
18✔
238
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
18✔
239
        int r;
18✔
240

241
        assert(netdev);
18✔
242
        assert(netdev->ifindex > 0);
18✔
243
        assert(netdev->manager);
18✔
244

245
        r = sd_genl_message_new(netdev->manager->genl, MACSEC_GENL_NAME, command, &m);
18✔
246
        if (r < 0)
18✔
247
                return r;
248

249
        r = sd_netlink_message_append_u32(m, MACSEC_ATTR_IFINDEX, netdev->ifindex);
18✔
250
        if (r < 0)
18✔
251
                return r;
252

253
        *ret = TAKE_PTR(m);
18✔
254

255
        return 0;
18✔
256
}
257

258
static int netdev_macsec_fill_message_sci(NetDev *netdev, MACsecSCI *sci, sd_netlink_message *m) {
14✔
259
        int r;
14✔
260

261
        assert(netdev);
14✔
262
        assert(m);
14✔
263
        assert(sci);
14✔
264

265
        r = sd_netlink_message_open_container(m, MACSEC_ATTR_RXSC_CONFIG);
14✔
266
        if (r < 0)
14✔
267
                return r;
268

269
        r = sd_netlink_message_append_u64(m, MACSEC_RXSC_ATTR_SCI, sci->as_uint64);
14✔
270
        if (r < 0)
14✔
271
                return r;
272

273
        r = sd_netlink_message_close_container(m);
14✔
274
        if (r < 0)
14✔
UNCOV
275
                return r;
×
276

277
        return 0;
278
}
279

280
static int netdev_macsec_fill_message_sa(NetDev *netdev, SecurityAssociation *a, sd_netlink_message *m) {
14✔
281
        int r;
14✔
282

283
        assert(netdev);
14✔
284
        assert(a);
14✔
285
        assert(m);
14✔
286

287
        r = sd_netlink_message_open_container(m, MACSEC_ATTR_SA_CONFIG);
14✔
288
        if (r < 0)
14✔
289
                return r;
290

291
        r = sd_netlink_message_append_u8(m, MACSEC_SA_ATTR_AN, a->association_number);
14✔
292
        if (r < 0)
14✔
293
                return r;
294

295
        if (a->packet_number > 0) {
14✔
296
                r = sd_netlink_message_append_u32(m, MACSEC_SA_ATTR_PN, a->packet_number);
10✔
297
                if (r < 0)
10✔
298
                        return r;
299
        }
300

301
        if (a->key_len > 0) {
14✔
302
                r = sd_netlink_message_append_data(m, MACSEC_SA_ATTR_KEYID, a->key_id, MACSEC_KEYID_LEN);
14✔
303
                if (r < 0)
14✔
304
                        return r;
305

306
                r = sd_netlink_message_append_data(m, MACSEC_SA_ATTR_KEY, a->key, a->key_len);
14✔
307
                if (r < 0)
14✔
308
                        return r;
309
        }
310

311
        if (a->activate >= 0) {
14✔
312
                r = sd_netlink_message_append_u8(m, MACSEC_SA_ATTR_ACTIVE, a->activate);
12✔
313
                if (r < 0)
12✔
314
                        return r;
315
        }
316

317
        r = sd_netlink_message_close_container(m);
14✔
318
        if (r < 0)
14✔
UNCOV
319
                return r;
×
320

321
        return 0;
322
}
323

324
static int macsec_receive_association_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
10✔
325
        int r;
10✔
326

327
        assert(netdev);
10✔
328
        assert(netdev->state != _NETDEV_STATE_INVALID);
10✔
329

330
        r = sd_netlink_message_get_errno(m);
10✔
331
        if (r == -EEXIST)
10✔
UNCOV
332
                log_netdev_info(netdev,
×
333
                                "MACsec receive secure association exists, using it without changing parameters");
334
        else if (r < 0) {
10✔
335
                log_netdev_warning_errno(netdev, r,
5✔
336
                                         "Failed to add receive secure association: %m");
337
                netdev_enter_failed(netdev);
5✔
338

339
                return 1;
5✔
340
        }
341

342
        log_netdev_debug(netdev, "Receive secure association is configured");
5✔
343

344
        return 1;
345
}
346

347
static int netdev_macsec_configure_receive_association(NetDev *netdev, ReceiveAssociation *a) {
10✔
348
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
10✔
349
        int r;
10✔
350

351
        assert(netdev);
10✔
352
        assert(a);
10✔
353

354
        if (!netdev_is_managed(netdev))
10✔
355
                return 0; /* Already detached, due to e.g. reloading .netdev files. */
356

357
        r = netdev_macsec_create_message(netdev, MACSEC_CMD_ADD_RXSA, &m);
10✔
358
        if (r < 0)
10✔
UNCOV
359
                return log_netdev_error_errno(netdev, r, "Failed to create netlink message: %m");
×
360

361
        r = netdev_macsec_fill_message_sa(netdev, &a->sa, m);
10✔
362
        if (r < 0)
10✔
UNCOV
363
                return log_netdev_error_errno(netdev, r, "Failed to fill netlink message: %m");
×
364

365
        r = netdev_macsec_fill_message_sci(netdev, &a->sci, m);
10✔
366
        if (r < 0)
10✔
UNCOV
367
                return log_netdev_error_errno(netdev, r, "Failed to fill netlink message: %m");
×
368

369
        r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_receive_association_handler,
10✔
370
                               netdev_destroy_callback, netdev);
371
        if (r < 0)
10✔
UNCOV
372
                return log_netdev_error_errno(netdev, r, "Failed to configure receive secure association: %m");
×
373

374
        netdev_ref(netdev);
10✔
375

376
        return 0;
377
}
378

379
static int macsec_receive_channel_handler(sd_netlink *rtnl, sd_netlink_message *m, ReceiveChannel *c) {
4✔
380
        assert(c);
4✔
381
        assert(c->macsec);
4✔
382

383
        NetDev *netdev = ASSERT_PTR(NETDEV(c->macsec));
4✔
384
        int r;
4✔
385

386
        assert(netdev->state != _NETDEV_STATE_INVALID);
4✔
387

388
        r = sd_netlink_message_get_errno(m);
4✔
389
        if (r == -EEXIST)
4✔
390
                log_netdev_debug(netdev,
2✔
391
                                 "MACsec receive channel exists, using it without changing parameters");
392
        else if (r < 0) {
2✔
UNCOV
393
                log_netdev_warning_errno(netdev, r,
×
394
                                         "Failed to add receive secure channel: %m");
UNCOV
395
                netdev_enter_failed(netdev);
×
396

UNCOV
397
                return 1;
×
398
        }
399

400
        log_netdev_debug(netdev, "Receive channel is configured");
4✔
401

402
        for (unsigned i = 0; i < c->n_rxsa; i++) {
14✔
403
                r = netdev_macsec_configure_receive_association(netdev, c->rxsa[i]);
10✔
404
                if (r < 0) {
10✔
UNCOV
405
                        log_netdev_warning_errno(netdev, r,
×
406
                                                 "Failed to configure receive security association: %m");
407
                        netdev_enter_failed(netdev);
×
UNCOV
408
                        return 1;
×
409
                }
410
        }
411

412
        return 1;
413
}
414

415
static void receive_channel_destroy_callback(ReceiveChannel *c) {
4✔
416
        assert(c);
4✔
417
        assert(c->macsec);
4✔
418

419
        netdev_unref(NETDEV(c->macsec));
4✔
420
}
4✔
421

422
static int netdev_macsec_configure_receive_channel(NetDev *netdev, ReceiveChannel *c) {
4✔
423
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
4✔
424
        int r;
4✔
425

426
        assert(netdev);
4✔
427
        assert(c);
4✔
428

429
        if (!netdev_is_managed(netdev))
4✔
430
                return 0; /* Already detached, due to e.g. reloading .netdev files. */
431

432
        r = netdev_macsec_create_message(netdev, MACSEC_CMD_ADD_RXSC, &m);
4✔
433
        if (r < 0)
4✔
UNCOV
434
                return log_netdev_error_errno(netdev, r, "Failed to create netlink message: %m");
×
435

436
        r = netdev_macsec_fill_message_sci(netdev, &c->sci, m);
4✔
437
        if (r < 0)
4✔
UNCOV
438
                return log_netdev_error_errno(netdev, r, "Failed to fill netlink message: %m");
×
439

440
        r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_receive_channel_handler,
4✔
441
                               receive_channel_destroy_callback, c);
442
        if (r < 0)
4✔
UNCOV
443
                return log_netdev_error_errno(netdev, r, "Failed to configure receive channel: %m");
×
444

445
        netdev_ref(netdev);
4✔
446

447
        return 0;
448
}
449

450
static int macsec_transmit_association_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
4✔
451
        int r;
4✔
452

453
        assert(netdev);
4✔
454
        assert(netdev->state != _NETDEV_STATE_INVALID);
4✔
455

456
        r = sd_netlink_message_get_errno(m);
4✔
457
        if (r == -EEXIST)
4✔
UNCOV
458
                log_netdev_info(netdev,
×
459
                                "MACsec transmit secure association exists, using it without changing parameters");
460
        else if (r < 0) {
4✔
461
                log_netdev_warning_errno(netdev, r,
2✔
462
                                         "Failed to add transmit secure association: %m");
463
                netdev_enter_failed(netdev);
2✔
464

465
                return 1;
2✔
466
        }
467

468
        log_netdev_debug(netdev, "Transmit secure association is configured");
2✔
469

470
        return 1;
471
}
472

473
static int netdev_macsec_configure_transmit_association(NetDev *netdev, TransmitAssociation *a) {
4✔
474
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
4✔
475
        int r;
4✔
476

477
        assert(netdev);
4✔
478
        assert(a);
4✔
479

480
        if (!netdev_is_managed(netdev))
4✔
481
                return 0; /* Already detached, due to e.g. reloading .netdev files. */
482

483
        r = netdev_macsec_create_message(netdev, MACSEC_CMD_ADD_TXSA, &m);
4✔
484
        if (r < 0)
4✔
UNCOV
485
                return log_netdev_error_errno(netdev, r, "Failed to create netlink message: %m");
×
486

487
        r = netdev_macsec_fill_message_sa(netdev, &a->sa, m);
4✔
488
        if (r < 0)
4✔
UNCOV
489
                return log_netdev_error_errno(netdev, r, "Failed to fill netlink message: %m");
×
490

491
        r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_transmit_association_handler,
4✔
492
                               netdev_destroy_callback, netdev);
493
        if (r < 0)
4✔
UNCOV
494
                return log_netdev_error_errno(netdev, r, "Failed to configure transmit secure association: %m");
×
495

496
        netdev_ref(netdev);
4✔
497

498
        return 0;
499
}
500

501
static int netdev_macsec_configure(NetDev *netdev, Link *link) {
2✔
502
        MACsec *s = MACSEC(netdev);
2✔
503
        TransmitAssociation *a;
2✔
504
        ReceiveChannel *c;
2✔
505
        int r;
2✔
506

507
        ORDERED_HASHMAP_FOREACH(a, s->transmit_associations_by_section) {
6✔
508
                r = netdev_macsec_configure_transmit_association(netdev, a);
4✔
509
                if (r < 0)
4✔
UNCOV
510
                        return r;
×
511
        }
512

513
        ORDERED_HASHMAP_FOREACH(c, s->receive_channels) {
6✔
514
                r = netdev_macsec_configure_receive_channel(netdev, c);
4✔
515
                if (r < 0)
4✔
UNCOV
516
                        return r;
×
517
        }
518

519
        return 0;
2✔
520
}
521

522
static int netdev_macsec_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
2✔
523
        assert(m);
2✔
524

525
        MACsec *v = MACSEC(netdev);
2✔
526
        int r;
2✔
527

528
        if (v->encrypt >= 0) {
2✔
529
                r = sd_netlink_message_append_u8(m, IFLA_MACSEC_ENCRYPT, v->encrypt);
2✔
530
                if (r < 0)
2✔
531
                        return r;
532
        }
533

534
        r = sd_netlink_message_append_u8(m, IFLA_MACSEC_ENCODING_SA, v->encoding_an);
2✔
535
        if (r < 0)
2✔
536
                return r;
537

538
        /* The properties below cannot be updated, and the kernel refuses the whole request if one of the
539
         * following attributes is set for an existing interface. */
540
        if (netdev->ifindex > 0)
2✔
541
                return 0;
542

543
        if (v->port > 0) {
1✔
544
                r = sd_netlink_message_append_u16(m, IFLA_MACSEC_PORT, v->port);
1✔
545
                if (r < 0)
1✔
UNCOV
546
                        return r;
×
547
        }
548

549
        /* Currently not supported by networkd, but IFLA_MACSEC_CIPHER_SUITE, IFLA_MACSEC_ICV_LEN, and
550
         * IFLA_MACSEC_SCI can neither set for an existing interface. */
551

552
        return 0;
553
}
554

555
int config_parse_macsec_port(
16✔
556
                const char *unit,
557
                const char *filename,
558
                unsigned line,
559
                const char *section,
560
                unsigned section_line,
561
                const char *lvalue,
562
                int ltype,
563
                const char *rvalue,
564
                void *data,
565
                void *userdata) {
566

567
        assert(filename);
16✔
568
        assert(section);
16✔
569
        assert(lvalue);
16✔
570
        assert(rvalue);
16✔
571
        assert(data);
16✔
572

573
        MACsec *s = ASSERT_PTR(userdata);
16✔
574
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
16✔
575
        _cleanup_(macsec_receive_channel_free_or_set_invalidp) ReceiveChannel *c = NULL;
16✔
576
        uint16_t port;
16✔
577
        void *dest;
16✔
578
        int r;
16✔
579

580
        /* This parses port used to make Secure Channel Identifier (SCI) */
581

582
        if (streq(section, "MACsec"))
16✔
583
                dest = &s->port;
2✔
584
        else if (streq(section, "MACsecReceiveChannel")) {
14✔
585
                r = macsec_receive_channel_new_static(s, filename, section_line, &c);
2✔
586
                if (r < 0)
2✔
UNCOV
587
                        return log_oom();
×
588

589
                dest = &c->sci.port;
2✔
590
        } else {
591
                assert(streq(section, "MACsecReceiveAssociation"));
12✔
592

593
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
12✔
594
                if (r < 0)
12✔
UNCOV
595
                        return log_oom();
×
596

597
                dest = &b->sci.port;
12✔
598
        }
599

600
        r = parse_ip_port(rvalue, &port);
16✔
601
        if (r < 0) {
16✔
UNCOV
602
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
603
                           "Failed to parse port '%s' for secure channel identifier. Ignoring assignment: %m",
604
                           rvalue);
UNCOV
605
                return 0;
×
606
        }
607

608
        unaligned_write_be16(dest, port);
16✔
609

610
        TAKE_PTR(b);
16✔
611
        TAKE_PTR(c);
16✔
612

613
        return 0;
16✔
614
}
615

616
int config_parse_macsec_hw_address(
14✔
617
                const char *unit,
618
                const char *filename,
619
                unsigned line,
620
                const char *section,
621
                unsigned section_line,
622
                const char *lvalue,
623
                int ltype,
624
                const char *rvalue,
625
                void *data,
626
                void *userdata) {
627

628
        assert(filename);
14✔
629
        assert(section);
14✔
630
        assert(lvalue);
14✔
631
        assert(rvalue);
14✔
632
        assert(data);
14✔
633

634
        MACsec *s = ASSERT_PTR(userdata);
14✔
635
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
14✔
636
        _cleanup_(macsec_receive_channel_free_or_set_invalidp) ReceiveChannel *c = NULL;
14✔
637
        int r;
14✔
638

639
        if (streq(section, "MACsecReceiveChannel"))
14✔
640
                r = macsec_receive_channel_new_static(s, filename, section_line, &c);
2✔
641
        else
642
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
12✔
643
        if (r < 0)
14✔
UNCOV
644
                return log_oom();
×
645

646
        r = parse_ether_addr(rvalue, b ? &b->sci.mac : &c->sci.mac);
14✔
647
        if (r < 0) {
14✔
UNCOV
648
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
649
                           "Failed to parse MAC address for secure channel identifier. "
650
                           "Ignoring assignment: %s", rvalue);
UNCOV
651
                return 0;
×
652
        }
653

654
        TAKE_PTR(b);
14✔
655
        TAKE_PTR(c);
14✔
656

657
        return 0;
14✔
658
}
659

660
int config_parse_macsec_packet_number(
10✔
661
                const char *unit,
662
                const char *filename,
663
                unsigned line,
664
                const char *section,
665
                unsigned section_line,
666
                const char *lvalue,
667
                int ltype,
668
                const char *rvalue,
669
                void *data,
670
                void *userdata) {
671

672
        assert(filename);
10✔
673
        assert(section);
10✔
674
        assert(lvalue);
10✔
675
        assert(rvalue);
10✔
676
        assert(data);
10✔
677

678
        MACsec *s = ASSERT_PTR(userdata);
10✔
679
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
10✔
680
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
10✔
681
        uint32_t val, *dest;
10✔
682
        int r;
10✔
683

684
        if (streq(section, "MACsecTransmitAssociation"))
10✔
685
                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
4✔
686
        else
687
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
6✔
688
        if (r < 0)
10✔
UNCOV
689
                return log_oom();
×
690

691
        dest = a ? &a->sa.packet_number : &b->sa.packet_number;
10✔
692

693
        r = safe_atou32(rvalue, &val);
10✔
694
        if (r < 0) {
10✔
UNCOV
695
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
696
                           "Failed to parse packet number. Ignoring assignment: %s", rvalue);
UNCOV
697
                return 0;
×
698
        }
699
        if (streq(section, "MACsecTransmitAssociation") && val == 0) {
10✔
UNCOV
700
                log_syntax(unit, LOG_WARNING, filename, line, 0,
×
701
                           "Invalid packet number. Ignoring assignment: %s", rvalue);
UNCOV
702
                return 0;
×
703
        }
704

705
        *dest = val;
10✔
706
        TAKE_PTR(a);
10✔
707
        TAKE_PTR(b);
10✔
708

709
        return 0;
10✔
710
}
711

712
int config_parse_macsec_key(
14✔
713
                const char *unit,
714
                const char *filename,
715
                unsigned line,
716
                const char *section,
717
                unsigned section_line,
718
                const char *lvalue,
719
                int ltype,
720
                const char *rvalue,
721
                void *data,
722
                void *userdata) {
723

724
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
14✔
UNCOV
725
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
×
726
        _cleanup_(erase_and_freep) void *p = NULL;
14✔
727
        MACsec *s = userdata;
14✔
728
        SecurityAssociation *dest;
14✔
729
        size_t l;
14✔
730
        int r;
14✔
731

732
        assert(filename);
14✔
733
        assert(section);
14✔
734
        assert(lvalue);
14✔
735
        assert(rvalue);
14✔
736
        assert(data);
14✔
737

738
        (void) warn_file_is_world_accessible(filename, NULL, unit, line);
14✔
739

740
        if (streq(section, "MACsecTransmitAssociation"))
14✔
741
                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
4✔
742
        else
743
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
10✔
744
        if (r < 0)
14✔
UNCOV
745
                return log_oom();
×
746

747
        dest = a ? &a->sa : &b->sa;
14✔
748

749
        r = unhexmem_full(rvalue, SIZE_MAX, /* secure = */ true, &p, &l);
14✔
750
        if (r < 0) {
14✔
751
                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse key. Ignoring assignment: %m");
×
UNCOV
752
                return 0;
×
753
        }
754

755
        if (l != 16) {
14✔
756
                /* See DEFAULT_SAK_LEN in drivers/net/macsec.c */
757
                log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid key length (%zu). Ignoring assignment", l);
×
UNCOV
758
                return 0;
×
759
        }
760

761
        explicit_bzero_safe(dest->key, dest->key_len);
14✔
762
        free_and_replace(dest->key, p);
14✔
763
        dest->key_len = l;
14✔
764

765
        TAKE_PTR(a);
14✔
766
        TAKE_PTR(b);
14✔
767

768
        return 0;
14✔
769
}
770

771
int config_parse_macsec_key_file(
2✔
772
                const char *unit,
773
                const char *filename,
774
                unsigned line,
775
                const char *section,
776
                unsigned section_line,
777
                const char *lvalue,
778
                int ltype,
779
                const char *rvalue,
780
                void *data,
781
                void *userdata) {
782

783
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
2✔
UNCOV
784
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
×
785
        _cleanup_free_ char *path = NULL;
2✔
786
        MACsec *s = userdata;
2✔
787
        char **dest;
2✔
788
        int r;
2✔
789

790
        assert(filename);
2✔
791
        assert(section);
2✔
792
        assert(lvalue);
2✔
793
        assert(rvalue);
2✔
794
        assert(data);
2✔
795

796
        if (streq(section, "MACsecTransmitAssociation"))
2✔
UNCOV
797
                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
×
798
        else
799
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
2✔
800
        if (r < 0)
2✔
UNCOV
801
                return log_oom();
×
802

803
        dest = a ? &a->sa.key_file : &b->sa.key_file;
2✔
804

805
        if (isempty(rvalue)) {
2✔
806
                *dest = mfree(*dest);
×
UNCOV
807
                return 0;
×
808
        }
809

810
        path = strdup(rvalue);
2✔
811
        if (!path)
2✔
UNCOV
812
                return log_oom();
×
813

814
        if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue) < 0)
2✔
815
                return 0;
816

817
        free_and_replace(*dest, path);
2✔
818
        TAKE_PTR(a);
2✔
819
        TAKE_PTR(b);
2✔
820

821
        return 0;
2✔
822
}
823

824
int config_parse_macsec_key_id(
16✔
825
                const char *unit,
826
                const char *filename,
827
                unsigned line,
828
                const char *section,
829
                unsigned section_line,
830
                const char *lvalue,
831
                int ltype,
832
                const char *rvalue,
833
                void *data,
834
                void *userdata) {
835

836
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
16✔
UNCOV
837
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
×
838
        _cleanup_free_ void *p = NULL;
16✔
839
        MACsec *s = userdata;
16✔
840
        uint8_t *dest;
16✔
841
        size_t l;
16✔
842
        int r;
16✔
843

844
        assert(filename);
16✔
845
        assert(section);
16✔
846
        assert(lvalue);
16✔
847
        assert(rvalue);
16✔
848
        assert(data);
16✔
849

850
        if (streq(section, "MACsecTransmitAssociation"))
16✔
851
                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
4✔
852
        else
853
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
12✔
854
        if (r < 0)
16✔
UNCOV
855
                return log_oom();
×
856

857
        r = unhexmem(rvalue, &p, &l);
16✔
858
        if (r == -ENOMEM)
16✔
UNCOV
859
                return log_oom();
×
860
        if (r < 0) {
16✔
UNCOV
861
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
862
                           "Failed to parse KeyId=%s, ignoring assignment: %m", rvalue);
UNCOV
863
                return 0;
×
864
        }
865
        if (l > MACSEC_KEYID_LEN) {
16✔
UNCOV
866
                log_syntax(unit, LOG_WARNING, filename, line, 0,
×
867
                           "Specified KeyId= is larger then the allowed maximum (%zu > %i), ignoring: %s",
868
                           l, MACSEC_KEYID_LEN, rvalue);
UNCOV
869
                return 0;
×
870
        }
871

872
        dest = a ? a->sa.key_id : b->sa.key_id;
16✔
873
        memcpy_safe(dest, p, l);
16✔
874
        memzero(dest + l, MACSEC_KEYID_LEN - l);
16✔
875

876
        TAKE_PTR(a);
16✔
877
        TAKE_PTR(b);
16✔
878

879
        return 0;
16✔
880
}
881

882
int config_parse_macsec_sa_activate(
12✔
883
                const char *unit,
884
                const char *filename,
885
                unsigned line,
886
                const char *section,
887
                unsigned section_line,
888
                const char *lvalue,
889
                int ltype,
890
                const char *rvalue,
891
                void *data,
892
                void *userdata) {
893

894
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
12✔
895
        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
12✔
896
        MACsec *s = userdata;
12✔
897
        int *dest, r;
12✔
898

899
        assert(filename);
12✔
900
        assert(section);
12✔
901
        assert(lvalue);
12✔
902
        assert(rvalue);
12✔
903
        assert(data);
12✔
904

905
        if (streq(section, "MACsecTransmitAssociation"))
12✔
906
                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
2✔
907
        else
908
                r = macsec_receive_association_new_static(s, filename, section_line, &b);
10✔
909
        if (r < 0)
12✔
UNCOV
910
                return log_oom();
×
911

912
        dest = a ? &a->sa.activate : &b->sa.activate;
12✔
913

914
        r = parse_tristate(rvalue, dest);
12✔
915
        if (r < 0) {
12✔
UNCOV
916
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
917
                           "Failed to parse activation mode of %s security association. "
918
                           "Ignoring assignment: %s",
919
                           streq(section, "MACsecTransmitAssociation") ? "transmit" : "receive",
920
                           rvalue);
UNCOV
921
                return 0;
×
922
        }
923

924
        TAKE_PTR(a);
12✔
925
        TAKE_PTR(b);
12✔
926

927
        return 0;
12✔
928
}
929

930
int config_parse_macsec_use_for_encoding(
2✔
931
                const char *unit,
932
                const char *filename,
933
                unsigned line,
934
                const char *section,
935
                unsigned section_line,
936
                const char *lvalue,
937
                int ltype,
938
                const char *rvalue,
939
                void *data,
940
                void *userdata) {
941

942
        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
2✔
943
        MACsec *s = userdata;
2✔
944
        int r;
2✔
945

946
        assert(filename);
2✔
947
        assert(section);
2✔
948
        assert(lvalue);
2✔
949
        assert(rvalue);
2✔
950
        assert(data);
2✔
951

952
        r = macsec_transmit_association_new_static(s, filename, section_line, &a);
2✔
953
        if (r < 0)
2✔
UNCOV
954
                return log_oom();
×
955

956
        if (isempty(rvalue)) {
2✔
957
                a->sa.use_for_encoding = -1;
×
958
                TAKE_PTR(a);
×
UNCOV
959
                return 0;
×
960
        }
961

962
        r = parse_tristate(rvalue, &a->sa.use_for_encoding);
2✔
963
        if (r < 0) {
2✔
UNCOV
964
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
965
                           "Failed to parse %s= setting. Ignoring assignment: %s",
966
                           lvalue, rvalue);
UNCOV
967
                return 0;
×
968
        }
969

970
        if (a->sa.use_for_encoding > 0)
2✔
971
                a->sa.activate = true;
2✔
972

973
        TAKE_PTR(a);
2✔
974

975
        return 0;
2✔
976
}
977

978
static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
16✔
979
        _cleanup_(erase_and_freep) uint8_t *key = NULL;
16✔
980
        size_t key_len;
16✔
981
        int r;
16✔
982

983
        assert(netdev);
16✔
984
        assert(sa);
16✔
985

986
        if (!sa->key_file)
16✔
987
                return 0;
988

989
        r = read_full_file_full(
2✔
990
                        AT_FDCWD, sa->key_file, UINT64_MAX, MACSEC_KEYID_LEN,
991
                        READ_FULL_FILE_SECURE |
992
                        READ_FULL_FILE_UNHEX |
993
                        READ_FULL_FILE_WARN_WORLD_READABLE |
994
                        READ_FULL_FILE_CONNECT_SOCKET |
995
                        READ_FULL_FILE_FAIL_WHEN_LARGER,
996
                        NULL, (char **) &key, &key_len);
997
        if (r < 0)
2✔
UNCOV
998
                return log_netdev_error_errno(netdev, r,
×
999
                                              "Failed to read key from '%s', ignoring: %m",
1000
                                              sa->key_file);
1001

1002
        if (key_len != MACSEC_KEYID_LEN)
2✔
UNCOV
1003
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1004
                                              "Invalid key length (%zu bytes), ignoring: %m", key_len);
1005

1006
        explicit_bzero_safe(sa->key, sa->key_len);
2✔
1007
        free_and_replace(sa->key, key);
2✔
1008
        sa->key_len = key_len;
2✔
1009

1010
        return 0;
2✔
1011
}
1012

1013
static int macsec_receive_channel_verify(ReceiveChannel *c) {
2✔
1014
        NetDev *netdev;
2✔
1015
        int r;
2✔
1016

1017
        assert(c);
2✔
1018
        assert(c->macsec);
2✔
1019

1020
        netdev = NETDEV(c->macsec);
2✔
1021

1022
        if (section_is_invalid(c->section))
2✔
1023
                return -EINVAL;
1024

1025
        if (ether_addr_is_null(&c->sci.mac))
2✔
UNCOV
1026
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1027
                                              "%s: MACsec receive channel without MAC address configured. "
1028
                                              "Ignoring [MACsecReceiveChannel] section from line %u",
1029
                                              c->section->filename, c->section->line);
1030

1031
        if (c->sci.port == 0)
2✔
UNCOV
1032
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1033
                                              "%s: MACsec receive channel without port configured. "
1034
                                              "Ignoring [MACsecReceiveChannel] section from line %u",
1035
                                              c->section->filename, c->section->line);
1036

1037
        r = ordered_hashmap_ensure_put(&c->macsec->receive_channels, &receive_channel_hash_ops, &c->sci.as_uint64, c);
2✔
1038
        if (r == -ENOMEM)
2✔
UNCOV
1039
                return log_oom();
×
1040
        if (r == -EEXIST)
2✔
UNCOV
1041
                return log_netdev_error_errno(netdev, r,
×
1042
                                              "%s: Multiple [MACsecReceiveChannel] sections have same SCI, "
1043
                                              "Ignoring [MACsecReceiveChannel] section from line %u",
1044
                                              c->section->filename, c->section->line);
1045
        if (r < 0)
2✔
UNCOV
1046
                return log_netdev_error_errno(netdev, r,
×
1047
                                              "%s: Failed to store [MACsecReceiveChannel] section at hashmap, "
1048
                                              "Ignoring [MACsecReceiveChannel] section from line %u",
1049
                                              c->section->filename, c->section->line);
1050
        return 0;
1051
}
1052

1053
static int macsec_transmit_association_verify(TransmitAssociation *t) {
4✔
1054
        NetDev *netdev;
4✔
1055
        int r;
4✔
1056

1057
        assert(t);
4✔
1058
        assert(t->macsec);
4✔
1059

1060
        netdev = NETDEV(t->macsec);
4✔
1061

1062
        if (section_is_invalid(t->section))
4✔
1063
                return -EINVAL;
1064

1065
        if (t->sa.packet_number == 0)
4✔
UNCOV
1066
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1067
                                              "%s: MACsec transmit secure association without PacketNumber= configured. "
1068
                                              "Ignoring [MACsecTransmitAssociation] section from line %u",
1069
                                              t->section->filename, t->section->line);
1070

1071
        r = macsec_read_key_file(netdev, &t->sa);
4✔
1072
        if (r < 0)
4✔
1073
                return r;
1074

1075
        if (t->sa.key_len <= 0)
4✔
UNCOV
1076
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1077
                                              "%s: MACsec transmit secure association without key configured. "
1078
                                              "Ignoring [MACsecTransmitAssociation] section from line %u",
1079
                                              t->section->filename, t->section->line);
1080

1081
        return 0;
1082
}
1083

1084
static int macsec_receive_association_verify(ReceiveAssociation *a) {
12✔
1085
        ReceiveChannel *c;
12✔
1086
        NetDev *netdev;
12✔
1087
        int r;
12✔
1088

1089
        assert(a);
12✔
1090
        assert(a->macsec);
12✔
1091

1092
        netdev = NETDEV(a->macsec);
12✔
1093

1094
        if (section_is_invalid(a->section))
12✔
1095
                return -EINVAL;
1096

1097
        r = macsec_read_key_file(netdev, &a->sa);
12✔
1098
        if (r < 0)
12✔
1099
                return r;
1100

1101
        if (a->sa.key_len <= 0)
12✔
UNCOV
1102
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1103
                                              "%s: MACsec receive secure association without key configured. "
1104
                                              "Ignoring [MACsecReceiveAssociation] section from line %u",
1105
                                              a->section->filename, a->section->line);
1106

1107
        if (ether_addr_is_null(&a->sci.mac))
12✔
UNCOV
1108
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1109
                                              "%s: MACsec receive secure association without MAC address configured. "
1110
                                              "Ignoring [MACsecReceiveAssociation] section from line %u",
1111
                                              a->section->filename, a->section->line);
1112

1113
        if (a->sci.port == 0)
12✔
UNCOV
1114
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
×
1115
                                              "%s: MACsec receive secure association without port configured. "
1116
                                              "Ignoring [MACsecReceiveAssociation] section from line %u",
1117
                                              a->section->filename, a->section->line);
1118

1119
        c = ordered_hashmap_get(a->macsec->receive_channels, &a->sci.as_uint64);
12✔
1120
        if (!c) {
12✔
UNCOV
1121
                _cleanup_(macsec_receive_channel_freep) ReceiveChannel *new_channel = NULL;
×
1122

1123
                r = macsec_receive_channel_new(a->macsec, a->sci.as_uint64, &new_channel);
2✔
1124
                if (r < 0)
2✔
UNCOV
1125
                        return log_oom();
×
1126

1127
                r = ordered_hashmap_ensure_put(&a->macsec->receive_channels, &receive_channel_hash_ops, &new_channel->sci.as_uint64, new_channel);
2✔
1128
                if (r == -ENOMEM)
2✔
UNCOV
1129
                        return log_oom();
×
1130
                if (r < 0)
2✔
UNCOV
1131
                        return log_netdev_error_errno(netdev, r,
×
1132
                                                      "%s: Failed to store receive channel at hashmap, "
1133
                                                      "Ignoring [MACsecReceiveAssociation] section from line %u",
1134
                                                      a->section->filename, a->section->line);
1135
                c = TAKE_PTR(new_channel);
2✔
1136
        }
1137
        if (c->n_rxsa >= MACSEC_MAX_ASSOCIATION_NUMBER)
12✔
1138
                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ERANGE),
2✔
1139
                                              "%s: Too many [MACsecReceiveAssociation] sections for the same receive channel, "
1140
                                              "Ignoring [MACsecReceiveAssociation] section from line %u",
1141
                                              a->section->filename, a->section->line);
1142

1143
        a->sa.association_number = c->n_rxsa;
10✔
1144
        c->rxsa[c->n_rxsa++] = a;
10✔
1145

1146
        return 0;
10✔
1147
}
1148

1149
static int netdev_macsec_verify(NetDev *netdev, const char *filename) {
2✔
1150
        assert(filename);
2✔
1151

1152
        MACsec *v = MACSEC(netdev);
2✔
1153
        TransmitAssociation *a;
2✔
1154
        ReceiveAssociation *n;
2✔
1155
        ReceiveChannel *c;
2✔
1156
        uint8_t an, encoding_an;
2✔
1157
        bool use_for_encoding;
2✔
1158
        int r;
2✔
1159

1160
        ORDERED_HASHMAP_FOREACH(c, v->receive_channels_by_section) {
6✔
1161
                r = macsec_receive_channel_verify(c);
2✔
1162
                if (r < 0)
2✔
UNCOV
1163
                        macsec_receive_channel_free(c);
×
1164
        }
1165

1166
        an = 0;
2✔
1167
        use_for_encoding = false;
2✔
1168
        encoding_an = 0;
2✔
1169
        ORDERED_HASHMAP_FOREACH(a, v->transmit_associations_by_section) {
6✔
1170
                r = macsec_transmit_association_verify(a);
4✔
1171
                if (r < 0) {
4✔
1172
                        macsec_transmit_association_free(a);
×
UNCOV
1173
                        continue;
×
1174
                }
1175

1176
                if (an >= MACSEC_MAX_ASSOCIATION_NUMBER) {
4✔
UNCOV
1177
                        log_netdev_error(netdev,
×
1178
                                         "%s: Too many [MACsecTransmitAssociation] sections configured. "
1179
                                         "Ignoring [MACsecTransmitAssociation] section from line %u",
1180
                                         a->section->filename, a->section->line);
1181
                        macsec_transmit_association_free(a);
×
UNCOV
1182
                        continue;
×
1183
                }
1184

1185
                a->sa.association_number = an++;
4✔
1186

1187
                if (a->sa.use_for_encoding > 0) {
4✔
1188
                        if (use_for_encoding) {
2✔
UNCOV
1189
                                log_netdev_warning(netdev,
×
1190
                                                   "%s: Multiple security associations are set to be used for transmit channel."
1191
                                                   "Disabling UseForEncoding= in [MACsecTransmitAssociation] section from line %u",
1192
                                                   a->section->filename, a->section->line);
UNCOV
1193
                                a->sa.use_for_encoding = false;
×
1194
                        } else {
1195
                                encoding_an = a->sa.association_number;
1196
                                use_for_encoding = true;
1197
                        }
1198
                }
1199
        }
1200

1201
        assert(encoding_an < MACSEC_MAX_ASSOCIATION_NUMBER);
2✔
1202
        v->encoding_an = encoding_an;
2✔
1203

1204
        ORDERED_HASHMAP_FOREACH(n, v->receive_associations_by_section) {
16✔
1205
                r = macsec_receive_association_verify(n);
12✔
1206
                if (r < 0)
12✔
1207
                        macsec_receive_association_free(n);
2✔
1208
        }
1209

1210
        return 0;
2✔
1211
}
1212

1213
static void macsec_init(NetDev *netdev) {
2✔
1214
        MACsec *v = MACSEC(netdev);
2✔
1215

1216
        v->encrypt = -1;
2✔
1217
}
2✔
1218

1219
static void macsec_done(NetDev *netdev) {
2✔
1220
        MACsec *v = MACSEC(netdev);
2✔
1221

1222
        ordered_hashmap_free(v->receive_channels);
2✔
1223
        ordered_hashmap_free(v->receive_channels_by_section);
2✔
1224
        ordered_hashmap_free(v->transmit_associations_by_section);
2✔
1225
        ordered_hashmap_free(v->receive_associations_by_section);
2✔
1226
}
2✔
1227

1228
const NetDevVTable macsec_vtable = {
1229
        .object_size = sizeof(MACsec),
1230
        .init = macsec_init,
1231
        .sections = NETDEV_COMMON_SECTIONS "MACsec\0MACsecReceiveChannel\0MACsecTransmitAssociation\0MACsecReceiveAssociation\0",
1232
        .fill_message_create = netdev_macsec_fill_message_create,
1233
        .post_create = netdev_macsec_configure,
1234
        .done = macsec_done,
1235
        .create_type = NETDEV_CREATE_STACKED,
1236
        .config_verify = netdev_macsec_verify,
1237
        .iftype = ARPHRD_ETHER,
1238
        .generate_mac = true,
1239
};
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