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

systemd / systemd / 23774132158

30 Mar 2026 09:35PM UTC coverage: 72.398% (+0.2%) from 72.208%
23774132158

push

github

daandemeyer
Only enable `NoAuto=true` for supported partitions

When `Format=empty` is set we need to check for `NoAuto` support for
the partition type, else we print a warning later in the build.

Followup for 381304a

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

7091 existing lines in 92 files now uncovered.

318474 of 439892 relevant lines covered (72.4%)

1151474.34 hits per line

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

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

3
#include <linux/if_arp.h>
4
#include <linux/if_macsec.h>
5

6
#include "sd-netlink.h"
7

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

22
#define SECURITY_ASSOCIATION_NULL               \
23
        (SecurityAssociation) {                 \
24
                .activate = -1,                 \
25
                .use_for_encoding = -1,         \
26
        }
27

28
static void security_association_clear(SecurityAssociation *sa) {
16✔
29
        if (!sa)
16✔
30
                return;
31

32
        explicit_bzero_safe(sa->key, sa->key_len);
16✔
33
        free(sa->key);
16✔
34
        free(sa->key_file);
16✔
35
}
36

37
static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c) {
12✔
38
        if (!c)
12✔
39
                return NULL;
40

41
        if (c->macsec && c->section)
12✔
42
                ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
12✔
43

44
        config_section_free(c->section);
12✔
45
        security_association_clear(&c->sa);
12✔
46

47
        return mfree(c);
12✔
48
}
49

50
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
148✔
51

52
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
10✔
53
                receive_association_hash_ops_by_section,
54
                ConfigSection, config_section_hash_func, config_section_compare_func,
55
                ReceiveAssociation, macsec_receive_association_free);
56

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

62
        assert(s);
64✔
63
        assert(ret);
64✔
64
        assert(filename);
64✔
65
        assert(section_line > 0);
64✔
66

67
        r = config_section_new(filename, section_line, &n);
64✔
68
        if (r < 0)
64✔
69
                return r;
70

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

77
        c = new(ReceiveAssociation, 1);
12✔
78
        if (!c)
12✔
79
                return -ENOMEM;
80

81
        *c = (ReceiveAssociation) {
12✔
82
                .macsec = s,
83
                .section = TAKE_PTR(n),
12✔
84
                .sa = SECURITY_ASSOCIATION_NULL,
85
        };
86

87
        r = ordered_hashmap_ensure_put(&s->receive_associations_by_section, &receive_association_hash_ops_by_section, c->section, c);
12✔
88
        if (r < 0)
12✔
89
                return r;
90

91
        *ret = TAKE_PTR(c);
12✔
92
        return 0;
12✔
93
}
94

95
static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
4✔
96
        if (!c)
4✔
97
                return NULL;
98

99
        if (c->macsec) {
4✔
100
                if (c->sci.as_uint64 > 0)
4✔
101
                        ordered_hashmap_remove_value(c->macsec->receive_channels, &c->sci.as_uint64, c);
4✔
102

103
                if (c->section)
4✔
104
                        ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section);
2✔
105
        }
106

107
        config_section_free(c->section);
4✔
108

109
        return mfree(c);
4✔
110
}
111

112
DEFINE_SECTION_CLEANUP_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
36✔
113

114
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
4✔
115
                receive_channel_hash_ops,
116
                uint64_t, uint64_hash_func, uint64_compare_func,
117
                ReceiveChannel, macsec_receive_channel_free);
118

119
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
×
120
                receive_channel_hash_ops_by_section,
121
                ConfigSection, config_section_hash_func, config_section_compare_func,
122
                ReceiveChannel, macsec_receive_channel_free);
123

124
static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) {
4✔
125
        ReceiveChannel *c;
4✔
126

127
        assert(s);
4✔
128
        assert(ret);
4✔
129

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

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

139
        *ret = c;
4✔
140
        return 0;
4✔
141
}
142

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

148
        assert(s);
4✔
149
        assert(ret);
4✔
150
        assert(filename);
4✔
151
        assert(section_line > 0);
4✔
152

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

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

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

167
        c->section = TAKE_PTR(n);
2✔
168

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

173
        *ret = TAKE_PTR(c);
2✔
174
        return 0;
2✔
175
}
176

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

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

184
        config_section_free(a->section);
4✔
185
        security_association_clear(&a->sa);
4✔
186

187
        return mfree(a);
4✔
188
}
189

190
DEFINE_SECTION_CLEANUP_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);
72✔
191

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

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

202
        assert(s);
16✔
203
        assert(ret);
16✔
204
        assert(filename);
16✔
205
        assert(section_line > 0);
16✔
206

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

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

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

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

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

231
        *ret = TAKE_PTR(a);
4✔
232
        return 0;
4✔
233
}
234

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

239
        assert(netdev);
18✔
240
        assert(netdev->ifindex > 0);
18✔
241
        assert(netdev->manager);
18✔
242

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

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

251
        *ret = TAKE_PTR(m);
18✔
252

253
        return 0;
18✔
254
}
255

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

259
        assert(netdev);
14✔
260
        assert(m);
14✔
261
        assert(sci);
14✔
262

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

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

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

275
        return 0;
276
}
277

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

281
        assert(netdev);
14✔
282
        assert(a);
14✔
283
        assert(m);
14✔
284

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

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

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

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

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

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

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

319
        return 0;
320
}
321

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

325
        assert(netdev);
10✔
326
        assert(netdev->state != _NETDEV_STATE_INVALID);
10✔
327

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

337
                return 1;
5✔
338
        }
339

340
        log_netdev_debug(netdev, "Receive secure association is configured");
5✔
341

342
        return 1;
343
}
344

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

349
        assert(netdev);
10✔
350
        assert(a);
10✔
351

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

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

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

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

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

372
        netdev_ref(netdev);
10✔
373

374
        return 0;
375
}
376

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

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

384
        assert(netdev->state != _NETDEV_STATE_INVALID);
4✔
385

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

UNCOV
395
                return 1;
×
396
        }
397

398
        log_netdev_debug(netdev, "Receive channel is configured");
4✔
399

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

410
        return 1;
411
}
412

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

417
        netdev_unref(NETDEV(c->macsec));
4✔
418
}
4✔
419

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

424
        assert(netdev);
4✔
425
        assert(c);
4✔
426

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

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

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

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

443
        netdev_ref(netdev);
4✔
444

445
        return 0;
446
}
447

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

451
        assert(netdev);
4✔
452
        assert(netdev->state != _NETDEV_STATE_INVALID);
4✔
453

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

463
                return 1;
2✔
464
        }
465

466
        log_netdev_debug(netdev, "Transmit secure association is configured");
2✔
467

468
        return 1;
469
}
470

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

475
        assert(netdev);
4✔
476
        assert(a);
4✔
477

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

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

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

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

494
        netdev_ref(netdev);
4✔
495

496
        return 0;
497
}
498

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

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

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

517
        return 0;
2✔
518
}
519

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

523
        MACsec *v = MACSEC(netdev);
2✔
524
        int r;
2✔
525

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

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

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

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

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

550
        return 0;
551
}
552

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

565
        assert(filename);
16✔
566
        assert(section);
16✔
567
        assert(lvalue);
16✔
568
        assert(rvalue);
16✔
569
        assert(data);
16✔
570

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

578
        /* This parses port used to make Secure Channel Identifier (SCI) */
579

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

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

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

595
                dest = &b->sci.port;
12✔
596
        }
597

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

606
        unaligned_write_be16(dest, port);
16✔
607

608
        TAKE_PTR(b);
16✔
609
        TAKE_PTR(c);
16✔
610

611
        return 0;
16✔
612
}
613

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

626
        assert(filename);
14✔
627
        assert(section);
14✔
628
        assert(lvalue);
14✔
629
        assert(rvalue);
14✔
630
        assert(data);
14✔
631

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

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

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

652
        TAKE_PTR(b);
14✔
653
        TAKE_PTR(c);
14✔
654

655
        return 0;
14✔
656
}
657

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

670
        assert(filename);
10✔
671
        assert(section);
10✔
672
        assert(lvalue);
10✔
673
        assert(rvalue);
10✔
674
        assert(data);
10✔
675

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

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

689
        dest = a ? &a->sa.packet_number : &b->sa.packet_number;
10✔
690

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

703
        *dest = val;
10✔
704
        TAKE_PTR(a);
10✔
705
        TAKE_PTR(b);
10✔
706

707
        return 0;
10✔
708
}
709

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

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

730
        assert(filename);
14✔
731
        assert(section);
14✔
732
        assert(lvalue);
14✔
733
        assert(rvalue);
14✔
734
        assert(data);
14✔
735

736
        (void) warn_file_is_world_accessible(filename, NULL, unit, line);
14✔
737

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

745
        dest = a ? &a->sa : &b->sa;
14✔
746

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

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

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

763
        TAKE_PTR(a);
14✔
764
        TAKE_PTR(b);
14✔
765

766
        return 0;
14✔
767
}
768

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

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

788
        assert(filename);
2✔
789
        assert(section);
2✔
790
        assert(lvalue);
2✔
791
        assert(rvalue);
2✔
792
        assert(data);
2✔
793

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

801
        dest = a ? &a->sa.key_file : &b->sa.key_file;
2✔
802

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

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

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

815
        free_and_replace(*dest, path);
2✔
816
        TAKE_PTR(a);
2✔
817
        TAKE_PTR(b);
2✔
818

819
        return 0;
2✔
820
}
821

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

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

842
        assert(filename);
16✔
843
        assert(section);
16✔
844
        assert(lvalue);
16✔
845
        assert(rvalue);
16✔
846
        assert(data);
16✔
847

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

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

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

874
        TAKE_PTR(a);
16✔
875
        TAKE_PTR(b);
16✔
876

877
        return 0;
16✔
878
}
879

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

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

897
        assert(filename);
12✔
898
        assert(section);
12✔
899
        assert(lvalue);
12✔
900
        assert(rvalue);
12✔
901
        assert(data);
12✔
902

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

910
        dest = a ? &a->sa.activate : &b->sa.activate;
12✔
911

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

922
        TAKE_PTR(a);
12✔
923
        TAKE_PTR(b);
12✔
924

925
        return 0;
12✔
926
}
927

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

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

944
        assert(filename);
2✔
945
        assert(section);
2✔
946
        assert(lvalue);
2✔
947
        assert(rvalue);
2✔
948
        assert(data);
2✔
949

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

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

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

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

971
        TAKE_PTR(a);
2✔
972

973
        return 0;
2✔
974
}
975

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

981
        assert(netdev);
16✔
982
        assert(sa);
16✔
983

984
        if (!sa->key_file)
16✔
985
                return 0;
986

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

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

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

1008
        return 0;
2✔
1009
}
1010

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

1015
        assert(c);
2✔
1016
        assert(c->macsec);
2✔
1017

1018
        netdev = NETDEV(c->macsec);
2✔
1019

1020
        if (section_is_invalid(c->section))
2✔
1021
                return -EINVAL;
1022

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

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

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

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

1055
        assert(t);
4✔
1056
        assert(t->macsec);
4✔
1057

1058
        netdev = NETDEV(t->macsec);
4✔
1059

1060
        if (section_is_invalid(t->section))
4✔
1061
                return -EINVAL;
1062

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

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

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

1079
        return 0;
1080
}
1081

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

1087
        assert(a);
12✔
1088
        assert(a->macsec);
12✔
1089

1090
        netdev = NETDEV(a->macsec);
12✔
1091

1092
        if (section_is_invalid(a->section))
12✔
1093
                return -EINVAL;
1094

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

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

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

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

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

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

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

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

1144
        return 0;
10✔
1145
}
1146

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

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

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

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

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

1183
                a->sa.association_number = an++;
4✔
1184

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

1199
        assert(encoding_an < MACSEC_MAX_ASSOCIATION_NUMBER);
2✔
1200
        v->encoding_an = encoding_an;
2✔
1201

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

1208
        return 0;
2✔
1209
}
1210

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

1214
        v->encrypt = -1;
2✔
1215
}
2✔
1216

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

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

1226
const NetDevVTable macsec_vtable = {
1227
        .object_size = sizeof(MACsec),
1228
        .init = macsec_init,
1229
        .sections = NETDEV_COMMON_SECTIONS "MACsec\0MACsecReceiveChannel\0MACsecTransmitAssociation\0MACsecReceiveAssociation\0",
1230
        .fill_message_create = netdev_macsec_fill_message_create,
1231
        .post_create = netdev_macsec_configure,
1232
        .done = macsec_done,
1233
        .create_type = NETDEV_CREATE_STACKED,
1234
        .config_verify = netdev_macsec_verify,
1235
        .iftype = ARPHRD_ETHER,
1236
        .generate_mac = true,
1237
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc