libnl: /data/src/libnl3/lib/route/link/macsec.c Source File

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