libnl 3.7.0
macsec.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2016 Sabrina Dubroca <sd@queasysnail.net>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup macsec MACsec
9 * MACsec link module
10 *
11 * @details
12 * \b Link Type Name: "macsec"
13 *
14 * @route_doc{link_macsec, MACsec Documentation}
15 *
16 * @{
17 */
18#include <netlink-private/netlink.h>
19#include <netlink/netlink.h>
20#include <netlink/attr.h>
21#include <netlink/utils.h>
22#include <netlink/object.h>
23#include <netlink/route/rtnl.h>
24#include <netlink/route/link/macsec.h>
25#include <netlink-private/route/link/api.h>
26#include <netlink-private/utils.h>
27
28#include <linux/if_macsec.h>
29
30/** @cond SKIP */
31#define MACSEC_ATTR_SCI (1 << 0)
32#define MACSEC_ATTR_ICV_LEN (1 << 1)
33#define MACSEC_ATTR_CIPHER_SUITE (1 << 2)
34#define MACSEC_ATTR_WINDOW (1 << 3)
35#define MACSEC_ATTR_ENCODING_SA (1 << 4)
36#define MACSEC_ATTR_ENCRYPT (1 << 5)
37#define MACSEC_ATTR_PROTECT (1 << 6)
38#define MACSEC_ATTR_INC_SCI (1 << 7)
39#define MACSEC_ATTR_ES (1 << 8)
40#define MACSEC_ATTR_SCB (1 << 9)
41#define MACSEC_ATTR_REPLAY_PROTECT (1 << 10)
42#define MACSEC_ATTR_VALIDATION (1 << 11)
43#define MACSEC_ATTR_PORT (1 << 12)
44#define MACSEC_ATTR_OFFLOAD (1 << 13)
45
46struct macsec_info {
47 int ifindex;
48 uint64_t sci;
49 uint16_t port;
50 uint64_t cipher_suite;
51 uint16_t icv_len;
52 uint32_t window;
53 enum macsec_validation_type validate;
54 uint8_t encoding_sa;
55
56 uint8_t send_sci, end_station, scb, replay_protect, protect, encrypt, offload;
57
58 uint32_t ce_mask;
59};
60
61#define DEFAULT_ICV_LEN 16
62
63/** @endcond */
64
65static struct nla_policy macsec_policy[IFLA_MACSEC_MAX+1] = {
66 [IFLA_MACSEC_SCI] = { .type = NLA_U64 },
67 [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 },
68 [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 },
69 [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 },
70 [IFLA_MACSEC_ENCODING_SA] = { .type = NLA_U8 },
71 [IFLA_MACSEC_ENCRYPT] = { .type = NLA_U8 },
72 [IFLA_MACSEC_PROTECT] = { .type = NLA_U8 },
73 [IFLA_MACSEC_INC_SCI] = { .type = NLA_U8 },
74 [IFLA_MACSEC_ES] = { .type = NLA_U8 },
75 [IFLA_MACSEC_SCB] = { .type = NLA_U8 },
76 [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 },
77 [IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 },
78 [IFLA_MACSEC_OFFLOAD] = { .type = NLA_U8 },
79};
80
81/**
82 * @name MACsec Object
83 * @{
84 */
85
86/**
87 * Allocate link object of type MACsec
88 *
89 * @return Allocated link object or NULL.
90 */
91static int macsec_alloc(struct rtnl_link *link)
92{
93 struct macsec_info *info;
94
95 if (!link->l_info) {
96 link->l_info = malloc(sizeof(struct macsec_info));
97 if (!link->l_info)
98 return -NLE_NOMEM;
99 }
100
101 memset(link->l_info, 0, sizeof(struct macsec_info));
102 info = link->l_info;
103
104 info->cipher_suite = MACSEC_DEFAULT_CIPHER_ID;
105 info->icv_len = DEFAULT_ICV_LEN;
106 info->ce_mask = MACSEC_ATTR_CIPHER_SUITE | MACSEC_ATTR_ICV_LEN;
107
108 return 0;
109}
110
111static int macsec_parse(struct rtnl_link *link, struct nlattr *data,
112 struct nlattr *xstats)
113{
114 struct nlattr *tb[IFLA_MACSEC_MAX+1];
115 struct macsec_info *info;
116 int err;
117
118 NL_DBG(3, "Parsing MACsec link info\n");
119
120 if ((err = nla_parse_nested(tb, IFLA_MACSEC_MAX, data, macsec_policy)) < 0)
121 goto errout;
122
123 if ((err = macsec_alloc(link)) < 0)
124 goto errout;
125
126 info = link->l_info;
127
128 if (tb[IFLA_MACSEC_SCI]) {
129 info->sci = nla_get_u64(tb[IFLA_MACSEC_SCI]);
130 info->ce_mask |= MACSEC_ATTR_SCI;
131 }
132
133 if (tb[IFLA_MACSEC_PROTECT]) {
134 info->protect = nla_get_u8(tb[IFLA_MACSEC_PROTECT]);
135 info->ce_mask |= MACSEC_ATTR_PROTECT;
136 }
137
138 if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
139 info->cipher_suite = nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
140 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
141 }
142
143 if (tb[IFLA_MACSEC_ICV_LEN]) {
144 info->icv_len = nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]);
145 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
146 }
147
148 if (tb[IFLA_MACSEC_ENCODING_SA]) {
149 info->encoding_sa = nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]);
150 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
151 }
152
153 if (tb[IFLA_MACSEC_VALIDATION]) {
154 info->validate = nla_get_u8(tb[IFLA_MACSEC_VALIDATION]);
155 info->ce_mask |= MACSEC_ATTR_VALIDATION;
156 }
157
158 if (tb[IFLA_MACSEC_ENCRYPT]) {
159 info->encrypt = nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]);
160 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
161 }
162
163 if (tb[IFLA_MACSEC_OFFLOAD]) {
164 info->offload = nla_get_u8(tb[IFLA_MACSEC_OFFLOAD]);
165 info->ce_mask |= MACSEC_ATTR_OFFLOAD;
166 }
167
168 if (tb[IFLA_MACSEC_INC_SCI]) {
169 info->send_sci = nla_get_u8(tb[IFLA_MACSEC_INC_SCI]);
170 info->ce_mask |= MACSEC_ATTR_INC_SCI;
171 }
172
173 if (tb[IFLA_MACSEC_ES]) {
174 info->end_station = nla_get_u8(tb[IFLA_MACSEC_ES]);
175 info->ce_mask |= MACSEC_ATTR_ES;
176 }
177
178 if (tb[IFLA_MACSEC_SCB]) {
179 info->scb = nla_get_u8(tb[IFLA_MACSEC_SCB]);
180 info->ce_mask |= MACSEC_ATTR_SCB;
181 }
182
183 if (tb[IFLA_MACSEC_REPLAY_PROTECT]) {
184 info->replay_protect = nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]);
185 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
186 }
187
188 if (tb[IFLA_MACSEC_WINDOW]) {
189 info->window = nla_get_u32(tb[IFLA_MACSEC_WINDOW]);
190 info->ce_mask |= MACSEC_ATTR_WINDOW;
191 }
192
193 err = 0;
194errout:
195 return err;
196}
197
198static void macsec_free(struct rtnl_link *link)
199{
200 free(link->l_info);
201 link->l_info = NULL;
202}
203
204static const char *values_on_off[] = { "off", "on" };
205
206static const char *VALIDATE_STR[] = {
207 [MACSEC_VALIDATE_DISABLED] = "disabled",
208 [MACSEC_VALIDATE_CHECK] = "check",
209 [MACSEC_VALIDATE_STRICT] = "strict",
210};
211
212static char *replay_protect_str(char *buf, uint8_t replay_protect, uint8_t window)
213{
214 if (replay_protect == 1) {
215 sprintf(buf, "replay_protect on window %d", window);
216 } else if (replay_protect == 0) {
217 sprintf(buf, "replay_protect off");
218 } else {
219 buf[0] = '\0';
220 }
221
222 return buf;
223}
224
225/** @cond SKIP */
226#define PRINT_FLAG(buf, i, field, c) ({ if (i->field == 1) *buf++ = c; })
227/** @endcond */
228static char *flags_str(char *buf, unsigned char len, struct macsec_info *info)
229{
230 char *tmp = buf;
231 memset(tmp, 0, len);
232
233 PRINT_FLAG(tmp, info, protect, 'P');
234 PRINT_FLAG(tmp, info, encrypt, 'E');
235 PRINT_FLAG(tmp, info, send_sci, 'S');
236 PRINT_FLAG(tmp, info, end_station, 'e');
237 PRINT_FLAG(tmp, info, scb, 's');
238 PRINT_FLAG(tmp, info, replay_protect, 'R');
239
240 *tmp++ = ' ';
241 *tmp++ = 'v';
242 switch (info->validate) {
243 case MACSEC_VALIDATE_DISABLED:
244 *tmp++ = 'd';
245 break;
246 case MACSEC_VALIDATE_CHECK:
247 *tmp++ = 'c';
248 break;
249 case MACSEC_VALIDATE_STRICT:
250 *tmp++ = 's';
251 break;
252 default:
253 break;
254 }
255
256 sprintf(tmp, " %d", info->encoding_sa);
257
258 return buf;
259}
260
261static void macsec_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
262{
263 struct macsec_info *info = link->l_info;
264 char tmp[128];
265
266 nl_dump(p, "sci %016llx <%s>", (long long unsigned)ntohll(info->sci),
267 flags_str(tmp, sizeof(tmp), info));
268}
269
270static void macsec_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
271{
272 struct macsec_info *info = link->l_info;
273 char tmp[128];
274
275 nl_dump(p,
276 " sci %016llx protect %s encoding_sa %d encrypt %s send_sci %s validate %s %s\n",
277 (long long unsigned)ntohll(info->sci),
278 values_on_off[info->protect], info->encoding_sa,
279 values_on_off[info->encrypt], values_on_off[info->send_sci],
280 VALIDATE_STR[info->validate],
281 replay_protect_str(tmp, info->replay_protect, info->window));
282 nl_dump(p, " cipher suite: %016llx, icv_len %d\n",
283 (long long unsigned)info->cipher_suite, info->icv_len);
284}
285
286static int macsec_clone(struct rtnl_link *dst, struct rtnl_link *src)
287{
288 struct macsec_info *copy, *info = src->l_info;
289 int err;
290
291 dst->l_info = NULL;
292 if ((err = rtnl_link_set_type(dst, "macsec")) < 0)
293 return err;
294 copy = dst->l_info;
295
296 if (!info || !copy)
297 return -NLE_NOMEM;
298
299 memcpy(copy, info, sizeof(struct macsec_info));
300
301 return 0;
302}
303
304static int macsec_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
305{
306 struct macsec_info *info = link->l_info;
307 struct nlattr *data;
308
309 if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
310 return -NLE_MSGSIZE;
311
312 if (info->ce_mask & MACSEC_ATTR_SCI)
313 NLA_PUT_U64(msg, IFLA_MACSEC_SCI, info->sci);
314 else if (info->ce_mask & MACSEC_ATTR_PORT)
315 NLA_PUT_U16(msg, IFLA_MACSEC_PORT, htons(info->port));
316
317 if ((info->ce_mask & MACSEC_ATTR_ENCRYPT))
318 NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, info->encrypt);
319
320 if ((info->ce_mask & MACSEC_ATTR_OFFLOAD))
321 NLA_PUT_U8(msg, IFLA_MACSEC_OFFLOAD, info->offload);
322
323 if (info->cipher_suite != MACSEC_DEFAULT_CIPHER_ID || info->icv_len != DEFAULT_ICV_LEN) {
324 NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, info->cipher_suite);
325 NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, info->icv_len);
326 }
327
328 if ((info->ce_mask & MACSEC_ATTR_INC_SCI))
329 NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, info->send_sci);
330
331 if ((info->ce_mask & MACSEC_ATTR_ES))
332 NLA_PUT_U8(msg, IFLA_MACSEC_ES, info->end_station);
333
334 if ((info->ce_mask & MACSEC_ATTR_SCB))
335 NLA_PUT_U8(msg, IFLA_MACSEC_SCB, info->scb);
336
337 if ((info->ce_mask & MACSEC_ATTR_PROTECT))
338 NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, info->protect);
339
340 if ((info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) {
341 if (info->replay_protect && !(info->ce_mask & MACSEC_ATTR_WINDOW))
342 return -NLE_INVAL;
343
344 NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, info->replay_protect);
345 NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, info->window);
346 }
347
348 if ((info->ce_mask & MACSEC_ATTR_VALIDATION))
349 NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, info->validate);
350
351 if ((info->ce_mask & MACSEC_ATTR_ENCODING_SA))
352 NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, info->encoding_sa);
353
354 nla_nest_end(msg, data);
355
356 return 0;
357
358nla_put_failure:
359 return -NLE_MSGSIZE;
360}
361
362static int macsec_compare(struct rtnl_link *link_a, struct rtnl_link *link_b,
363 int flags)
364{
365 struct macsec_info *a = link_a->l_info;
366 struct macsec_info *b = link_b->l_info;
367 int diff = 0;
368 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
369
370#define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR)
371
372 if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
373 diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
374 else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
375 diff |= MACSEC_DIFF(PORT, a->port != b->port);
376
377 if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
378 diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
379 diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
380 }
381
382 if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
383 int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
384 if (a->replay_protect && b->replay_protect)
385 d |= MACSEC_DIFF(WINDOW, a->window != b->window);
386 diff |= d;
387 }
388
389 diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
390 diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
391 diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
392 diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
393 diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
394 diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
395 diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
396#undef MACSEC_DIFF
397
398 return diff;
399}
400
401
402static struct rtnl_link_info_ops macsec_info_ops = {
403 .io_name = "macsec",
404 .io_alloc = macsec_alloc,
405 .io_parse = macsec_parse,
406 .io_dump = {
407 [NL_DUMP_LINE] = macsec_dump_line,
408 [NL_DUMP_DETAILS] = macsec_dump_details,
409 },
410 .io_clone = macsec_clone,
411 .io_put_attrs = macsec_put_attrs,
412 .io_free = macsec_free,
413 .io_compare = macsec_compare,
414};
415
416static void __init macsec_init(void)
417{
418 rtnl_link_register_info(&macsec_info_ops);
419}
420
421static void __exit macsec_exit(void)
422{
423 rtnl_link_unregister_info(&macsec_info_ops);
424}
425
426/** @cond SKIP */
427#define IS_MACSEC_LINK_ASSERT(link) \
428 if ((link)->l_info_ops != &macsec_info_ops) { \
429 APPBUG("Link is not a MACsec link. set type \"macsec\" first."); \
430 return -NLE_OPNOTSUPP; \
431 }
432/** @endcond */
433
434struct rtnl_link *rtnl_link_macsec_alloc(void)
435{
436 struct rtnl_link *link = rtnl_link_alloc();
437
438 if (!link)
439 return NULL;
440
441 if (rtnl_link_set_type(link, "macsec") < 0) {
442 rtnl_link_put(link);
443 return NULL;
444 }
445
446 return link;
447}
448
449/**
450 * Set SCI
451 * @arg link Link object
452 * @arg sci Secure Channel Identifier in network byte order
453 *
454 * @return 0 on success or a negative error code.
455 */
456int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci)
457{
458 struct macsec_info *info = link->l_info;
459
460 IS_MACSEC_LINK_ASSERT(link);
461
462 info->sci = sci;
463 info->ce_mask |= MACSEC_ATTR_SCI;
464
465 return 0;
466}
467
468/**
469 * Get SCI
470 * @arg link Link object
471 * @arg sci On return points to the Secure Channel Identifier
472 * in network byte order
473 *
474 * @return 0 on success or a negative error code.
475 */
476int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
477{
478 struct macsec_info *info = link->l_info;
479
480 IS_MACSEC_LINK_ASSERT(link);
481
482 if (!(info->ce_mask & MACSEC_ATTR_SCI))
483 return -NLE_NOATTR;
484
485 if (sci)
486 *sci = info->sci;
487
488 return 0;
489}
490
491/**
492 * Set port identifier
493 * @arg link Link object
494 * @arg port Port identifier in host byte order
495 *
496 * @return 0 on success or a negative error code.
497 */
498int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
499{
500 struct macsec_info *info = link->l_info;
501
502 IS_MACSEC_LINK_ASSERT(link);
503
504 info->port = port;
505 info->ce_mask |= MACSEC_ATTR_PORT;
506
507 return 0;
508}
509
510/**
511 * Get port identifier
512 * @arg link Link object
513 * @arg port On return points to the port identifier in host byte order
514 *
515 * @return 0 on success or a negative error code.
516 */
517int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
518{
519 struct macsec_info *info = link->l_info;
520
521 IS_MACSEC_LINK_ASSERT(link);
522
523 if (!(info->ce_mask & MACSEC_ATTR_PORT))
524 return -NLE_NOATTR;
525
526 if (port)
527 *port = info->port;
528
529 return 0;
530}
531
532int rtnl_link_macsec_set_cipher_suite(struct rtnl_link *link, uint64_t cipher_suite)
533{
534 struct macsec_info *info = link->l_info;
535
536 IS_MACSEC_LINK_ASSERT(link);
537
538 info->cipher_suite = cipher_suite;
539 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
540
541 return 0;
542}
543
544int rtnl_link_macsec_get_cipher_suite(struct rtnl_link *link, uint64_t *cs)
545{
546 struct macsec_info *info = link->l_info;
547
548 IS_MACSEC_LINK_ASSERT(link);
549
550 if (!(info->ce_mask & MACSEC_ATTR_CIPHER_SUITE))
551 return -NLE_NOATTR;
552
553 if (cs)
554 *cs = info->cipher_suite;
555
556 return 0;
557}
558
559int rtnl_link_macsec_set_icv_len(struct rtnl_link *link, uint16_t icv_len)
560{
561 struct macsec_info *info = link->l_info;
562
563 IS_MACSEC_LINK_ASSERT(link);
564
565 if (icv_len > MACSEC_STD_ICV_LEN)
566 return -NLE_INVAL;
567
568 info->icv_len = icv_len;
569 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
570
571 return 0;
572}
573
574int rtnl_link_macsec_get_icv_len(struct rtnl_link *link, uint16_t *icv_len)
575{
576 struct macsec_info *info = link->l_info;
577
578 IS_MACSEC_LINK_ASSERT(link);
579
580 if (!(info->ce_mask & MACSEC_ATTR_ICV_LEN))
581 return -NLE_NOATTR;
582
583 if (icv_len)
584 *icv_len = info->icv_len;
585
586 return 0;
587}
588
589int rtnl_link_macsec_set_protect(struct rtnl_link *link, uint8_t protect)
590{
591 struct macsec_info *info = link->l_info;
592
593 IS_MACSEC_LINK_ASSERT(link);
594
595 if (protect > 1)
596 return -NLE_INVAL;
597
598 info->protect = protect;
599 info->ce_mask |= MACSEC_ATTR_PROTECT;
600
601 return 0;
602}
603
604int rtnl_link_macsec_get_protect(struct rtnl_link *link, uint8_t *protect)
605{
606 struct macsec_info *info = link->l_info;
607
608 IS_MACSEC_LINK_ASSERT(link);
609
610 if (!(info->ce_mask & MACSEC_ATTR_PROTECT))
611 return -NLE_NOATTR;
612
613 if (protect)
614 *protect = info->protect;
615
616 return 0;
617}
618
619int rtnl_link_macsec_set_encrypt(struct rtnl_link *link, uint8_t encrypt)
620{
621 struct macsec_info *info = link->l_info;
622
623 IS_MACSEC_LINK_ASSERT(link);
624
625 if (encrypt > 1)
626 return -NLE_INVAL;
627
628 info->encrypt = encrypt;
629 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
630
631 return 0;
632}
633
634int rtnl_link_macsec_get_encrypt(struct rtnl_link *link, uint8_t *encrypt)
635{
636 struct macsec_info *info = link->l_info;
637
638 IS_MACSEC_LINK_ASSERT(link);
639
640 if (!(info->ce_mask & MACSEC_ATTR_ENCRYPT))
641 return -NLE_NOATTR;
642
643 if (encrypt)
644 *encrypt = info->encrypt;
645
646 return 0;
647}
648
649int rtnl_link_macsec_set_offload(struct rtnl_link *link, uint8_t offload)
650{
651 struct macsec_info *info = link->l_info;
652
653 IS_MACSEC_LINK_ASSERT(link);
654
655 if (offload > 1)
656 return -NLE_INVAL;
657
658 info->offload = offload;
659 info->ce_mask |= MACSEC_ATTR_OFFLOAD;
660
661 return 0;
662}
663
664int rtnl_link_macsec_get_offload(struct rtnl_link *link, uint8_t *offload)
665{
666 struct macsec_info *info = link->l_info;
667
668 IS_MACSEC_LINK_ASSERT(link);
669
670 if (!(info->ce_mask & MACSEC_ATTR_OFFLOAD))
671 return -NLE_NOATTR;
672
673 if (offload)
674 *offload = info->offload;
675
676 return 0;
677}
678
679int rtnl_link_macsec_set_encoding_sa(struct rtnl_link *link, uint8_t encoding_sa)
680{
681 struct macsec_info *info = link->l_info;
682
683 IS_MACSEC_LINK_ASSERT(link);
684
685 if (encoding_sa > 3)
686 return -NLE_INVAL;
687
688 info->encoding_sa = encoding_sa;
689 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
690
691 return 0;
692}
693
694int rtnl_link_macsec_get_encoding_sa(struct rtnl_link *link, uint8_t *encoding_sa)
695{
696 struct macsec_info *info = link->l_info;
697
698 IS_MACSEC_LINK_ASSERT(link);
699
700 if (!(info->ce_mask & MACSEC_ATTR_ENCODING_SA))
701 return -NLE_NOATTR;
702
703 if (encoding_sa)
704 *encoding_sa = info->encoding_sa;
705
706 return 0;
707}
708
709int rtnl_link_macsec_set_validation_type(struct rtnl_link *link, enum macsec_validation_type validate)
710{
711 struct macsec_info *info = link->l_info;
712
713 IS_MACSEC_LINK_ASSERT(link);
714
715 if (validate > MACSEC_VALIDATE_MAX)
716 return -NLE_INVAL;
717
718 info->validate = validate;
719 info->ce_mask |= MACSEC_ATTR_VALIDATION;
720
721 return 0;
722}
723
724int rtnl_link_macsec_get_validation_type(struct rtnl_link *link, enum macsec_validation_type *validate)
725{
726 struct macsec_info *info = link->l_info;
727
728 IS_MACSEC_LINK_ASSERT(link);
729
730 if (!(info->ce_mask & MACSEC_ATTR_VALIDATION))
731 return -NLE_NOATTR;
732
733 if (validate)
734 *validate = info->validate;
735
736 return 0;
737}
738
739int rtnl_link_macsec_set_replay_protect(struct rtnl_link *link, uint8_t replay_protect)
740{
741 struct macsec_info *info = link->l_info;
742
743 IS_MACSEC_LINK_ASSERT(link);
744
745 if (replay_protect > 1)
746 return -NLE_INVAL;
747
748 info->replay_protect = replay_protect;
749 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
750
751 return 0;
752}
753
754int rtnl_link_macsec_get_replay_protect(struct rtnl_link *link, uint8_t *replay_protect)
755{
756 struct macsec_info *info = link->l_info;
757
758 IS_MACSEC_LINK_ASSERT(link);
759
760 if (!(info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT))
761 return -NLE_NOATTR;
762
763 if (replay_protect)
764 *replay_protect = info->replay_protect;
765
766 return 0;
767}
768
769int rtnl_link_macsec_set_window(struct rtnl_link *link, uint32_t window)
770{
771 struct macsec_info *info = link->l_info;
772
773 IS_MACSEC_LINK_ASSERT(link);
774
775 info->window = window;
776 info->ce_mask |= MACSEC_ATTR_WINDOW;
777
778 return 0;
779}
780
781int rtnl_link_macsec_get_window(struct rtnl_link *link, uint32_t *window)
782{
783 struct macsec_info *info = link->l_info;
784
785 IS_MACSEC_LINK_ASSERT(link);
786
787 if (!(info->ce_mask & MACSEC_ATTR_WINDOW))
788 return -NLE_NOATTR;
789
790 if (window)
791 *window = info->window;
792
793 return 0;
794}
795
796int rtnl_link_macsec_set_send_sci(struct rtnl_link *link, uint8_t send_sci)
797{
798 struct macsec_info *info = link->l_info;
799
800 IS_MACSEC_LINK_ASSERT(link);
801
802 if (send_sci > 1)
803 return -NLE_INVAL;
804
805 info->send_sci = send_sci;
806 info->ce_mask |= MACSEC_ATTR_INC_SCI;
807
808 return 0;
809}
810
811int rtnl_link_macsec_get_send_sci(struct rtnl_link *link, uint8_t *send_sci)
812{
813 struct macsec_info *info = link->l_info;
814
815 IS_MACSEC_LINK_ASSERT(link);
816
817 if (!(info->ce_mask & MACSEC_ATTR_INC_SCI))
818 return -NLE_NOATTR;
819
820 if (send_sci)
821 *send_sci = info->send_sci;
822
823 return 0;
824}
825
826int rtnl_link_macsec_set_end_station(struct rtnl_link *link, uint8_t end_station)
827{
828 struct macsec_info *info = link->l_info;
829
830 IS_MACSEC_LINK_ASSERT(link);
831
832 if (end_station > 1)
833 return -NLE_INVAL;
834
835 info->end_station = end_station;
836 info->ce_mask |= MACSEC_ATTR_ES;
837
838 return 0;
839}
840
841int rtnl_link_macsec_get_end_station(struct rtnl_link *link, uint8_t *es)
842{
843 struct macsec_info *info = link->l_info;
844
845 IS_MACSEC_LINK_ASSERT(link);
846
847 if (!(info->ce_mask & MACSEC_ATTR_ES))
848 return -NLE_NOATTR;
849
850 if (es)
851 *es = info->end_station;
852
853 return 0;
854}
855
856int rtnl_link_macsec_set_scb(struct rtnl_link *link, uint8_t scb)
857{
858 struct macsec_info *info = link->l_info;
859
860 IS_MACSEC_LINK_ASSERT(link);
861
862 if (scb > 1)
863 return -NLE_INVAL;
864
865 info->scb = scb;
866 info->ce_mask |= MACSEC_ATTR_SCB;
867
868 return 0;
869}
870
871int rtnl_link_macsec_get_scb(struct rtnl_link *link, uint8_t *scb)
872{
873 struct macsec_info *info = link->l_info;
874
875 IS_MACSEC_LINK_ASSERT(link);
876
877 if (!(info->ce_mask & MACSEC_ATTR_SCB))
878 return -NLE_NOATTR;
879
880 if (scb)
881 *scb = info->scb;
882
883 return 0;
884}
885
886/** @} */
887
888/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:702
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:194
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
Definition: attr.c:757
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:602
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:898
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1016
#define NLA_PUT_U64(msg, attrtype, value)
Add 64 bit integer attribute to netlink message.
Definition: attr.h:248
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:961
@ NLA_U64
64 bit integer
Definition: attr.h:38
@ NLA_U8
8 bit integer
Definition: attr.h:35
@ NLA_U32
32 bit integer
Definition: attr.h:37
int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci)
Set SCI.
Definition: macsec.c:456
int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
Get SCI.
Definition: macsec.c:476
int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
Set port identifier.
Definition: macsec.c:498
int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
Get port identifier.
Definition: macsec.c:517
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65