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