libnl  3.6.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 
46 struct 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 
65 static 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  */
91 static 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 
111 static 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;
194 errout:
195  return err;
196 }
197 
198 static void macsec_free(struct rtnl_link *link)
199 {
200  free(link->l_info);
201  link->l_info = NULL;
202 }
203 
204 static const char *values_on_off[] = { "off", "on" };
205 
206 static const char *VALIDATE_STR[] = {
207  [MACSEC_VALIDATE_DISABLED] = "disabled",
208  [MACSEC_VALIDATE_CHECK] = "check",
209  [MACSEC_VALIDATE_STRICT] = "strict",
210 };
211 
212 static 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 */
228 static 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 
261 static 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>", ntohll(info->sci), flags_str(tmp, sizeof(tmp), info));
267 }
268 
269 static void macsec_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
270 {
271  struct macsec_info *info = link->l_info;
272  char tmp[128];
273 
274  nl_dump(p, " sci %016llx protect %s encoding_sa %d encrypt %s send_sci %s validate %s %s\n",
275  ntohll(info->sci), values_on_off[info->protect], info->encoding_sa, values_on_off[info->encrypt], values_on_off[info->send_sci],
276  VALIDATE_STR[info->validate],
277  replay_protect_str(tmp, info->replay_protect, info->window));
278  nl_dump(p, " cipher suite: %016llx, icv_len %d\n",
279  info->cipher_suite, info->icv_len);
280 }
281 
282 static int macsec_clone(struct rtnl_link *dst, struct rtnl_link *src)
283 {
284  struct macsec_info *copy, *info = src->l_info;
285  int err;
286 
287  dst->l_info = NULL;
288  if ((err = rtnl_link_set_type(dst, "macsec")) < 0)
289  return err;
290  copy = dst->l_info;
291 
292  if (!info || !copy)
293  return -NLE_NOMEM;
294 
295  memcpy(copy, info, sizeof(struct macsec_info));
296 
297  return 0;
298 }
299 
300 static int macsec_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
301 {
302  struct macsec_info *info = link->l_info;
303  struct nlattr *data;
304 
305  if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
306  return -NLE_MSGSIZE;
307 
308  if (info->ce_mask & MACSEC_ATTR_SCI)
309  NLA_PUT_U64(msg, IFLA_MACSEC_SCI, info->sci);
310  else if (info->ce_mask & MACSEC_ATTR_PORT)
311  NLA_PUT_U16(msg, IFLA_MACSEC_PORT, htons(info->port));
312 
313  if ((info->ce_mask & MACSEC_ATTR_ENCRYPT))
314  NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, info->encrypt);
315 
316  if ((info->ce_mask & MACSEC_ATTR_OFFLOAD))
317  NLA_PUT_U8(msg, IFLA_MACSEC_OFFLOAD, info->offload);
318 
319  if (info->cipher_suite != MACSEC_DEFAULT_CIPHER_ID || info->icv_len != DEFAULT_ICV_LEN) {
320  NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, info->cipher_suite);
321  NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, info->icv_len);
322  }
323 
324  if ((info->ce_mask & MACSEC_ATTR_INC_SCI))
325  NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, info->send_sci);
326 
327  if ((info->ce_mask & MACSEC_ATTR_ES))
328  NLA_PUT_U8(msg, IFLA_MACSEC_ES, info->end_station);
329 
330  if ((info->ce_mask & MACSEC_ATTR_SCB))
331  NLA_PUT_U8(msg, IFLA_MACSEC_SCB, info->scb);
332 
333  if ((info->ce_mask & MACSEC_ATTR_PROTECT))
334  NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, info->protect);
335 
336  if ((info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) {
337  if (info->replay_protect && !(info->ce_mask & MACSEC_ATTR_WINDOW))
338  return -NLE_INVAL;
339 
340  NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, info->replay_protect);
341  NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, info->window);
342  }
343 
344  if ((info->ce_mask & MACSEC_ATTR_VALIDATION))
345  NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, info->validate);
346 
347  if ((info->ce_mask & MACSEC_ATTR_ENCODING_SA))
348  NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, info->encoding_sa);
349 
350  nla_nest_end(msg, data);
351 
352  return 0;
353 
354 nla_put_failure:
355  return -NLE_MSGSIZE;
356 }
357 
358 static int macsec_compare(struct rtnl_link *link_a, struct rtnl_link *link_b,
359  int flags)
360 {
361  struct macsec_info *a = link_a->l_info;
362  struct macsec_info *b = link_b->l_info;
363  int diff = 0;
364  uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
365 
366 #define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR)
367 
368  if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
369  diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
370  else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
371  diff |= MACSEC_DIFF(PORT, a->port != b->port);
372 
373  if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
374  diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
375  diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
376  }
377 
378  if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
379  int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
380  if (a->replay_protect && b->replay_protect)
381  d |= MACSEC_DIFF(WINDOW, a->window != b->window);
382  diff |= d;
383  }
384 
385  diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
386  diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
387  diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
388  diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
389  diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
390  diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
391  diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
392 #undef MACSEC_DIFF
393 
394  return diff;
395 }
396 
397 
398 static struct rtnl_link_info_ops macsec_info_ops = {
399  .io_name = "macsec",
400  .io_alloc = macsec_alloc,
401  .io_parse = macsec_parse,
402  .io_dump = {
403  [NL_DUMP_LINE] = macsec_dump_line,
404  [NL_DUMP_DETAILS] = macsec_dump_details,
405  },
406  .io_clone = macsec_clone,
407  .io_put_attrs = macsec_put_attrs,
408  .io_free = macsec_free,
409  .io_compare = macsec_compare,
410 };
411 
412 static void __init macsec_init(void)
413 {
414  rtnl_link_register_info(&macsec_info_ops);
415 }
416 
417 static void __exit macsec_exit(void)
418 {
419  rtnl_link_unregister_info(&macsec_info_ops);
420 }
421 
422 /** @cond SKIP */
423 #define IS_MACSEC_LINK_ASSERT(link) \
424  if ((link)->l_info_ops != &macsec_info_ops) { \
425  APPBUG("Link is not a MACsec link. set type \"macsec\" first."); \
426  return -NLE_OPNOTSUPP; \
427  }
428 /** @endcond */
429 
430 struct rtnl_link *rtnl_link_macsec_alloc(void)
431 {
432  struct rtnl_link *link = rtnl_link_alloc();
433 
434  if (!link)
435  return NULL;
436 
437  if (rtnl_link_set_type(link, "macsec") < 0) {
438  rtnl_link_put(link);
439  return NULL;
440  }
441 
442  return link;
443 }
444 
445 /**
446  * Set SCI
447  * @arg link Link object
448  * @arg sci Secure Channel Identifier in network byte order
449  *
450  * @return 0 on success or a negative error code.
451  */
452 int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci)
453 {
454  struct macsec_info *info = link->l_info;
455 
456  IS_MACSEC_LINK_ASSERT(link);
457 
458  info->sci = sci;
459  info->ce_mask |= MACSEC_ATTR_SCI;
460 
461  return 0;
462 }
463 
464 /**
465  * Get SCI
466  * @arg link Link object
467  * @arg sci On return points to the Secure Channel Identifier
468  * in network byte order
469  *
470  * @return 0 on success or a negative error code.
471  */
472 int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
473 {
474  struct macsec_info *info = link->l_info;
475 
476  IS_MACSEC_LINK_ASSERT(link);
477 
478  if (!(info->ce_mask & MACSEC_ATTR_SCI))
479  return -NLE_NOATTR;
480 
481  if (sci)
482  *sci = info->sci;
483 
484  return 0;
485 }
486 
487 /**
488  * Set port identifier
489  * @arg link Link object
490  * @arg port Port identifier in host byte order
491  *
492  * @return 0 on success or a negative error code.
493  */
494 int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
495 {
496  struct macsec_info *info = link->l_info;
497 
498  IS_MACSEC_LINK_ASSERT(link);
499 
500  info->port = port;
501  info->ce_mask |= MACSEC_ATTR_PORT;
502 
503  return 0;
504 }
505 
506 /**
507  * Get port identifier
508  * @arg link Link object
509  * @arg port On return points to the port identifier in host byte order
510  *
511  * @return 0 on success or a negative error code.
512  */
513 int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
514 {
515  struct macsec_info *info = link->l_info;
516 
517  IS_MACSEC_LINK_ASSERT(link);
518 
519  if (!(info->ce_mask & MACSEC_ATTR_PORT))
520  return -NLE_NOATTR;
521 
522  if (port)
523  *port = info->port;
524 
525  return 0;
526 }
527 
528 int rtnl_link_macsec_set_cipher_suite(struct rtnl_link *link, uint64_t cipher_suite)
529 {
530  struct macsec_info *info = link->l_info;
531 
532  IS_MACSEC_LINK_ASSERT(link);
533 
534  info->cipher_suite = cipher_suite;
535  info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
536 
537  return 0;
538 }
539 
540 int rtnl_link_macsec_get_cipher_suite(struct rtnl_link *link, uint64_t *cs)
541 {
542  struct macsec_info *info = link->l_info;
543 
544  IS_MACSEC_LINK_ASSERT(link);
545 
546  if (!(info->ce_mask & MACSEC_ATTR_CIPHER_SUITE))
547  return -NLE_NOATTR;
548 
549  if (cs)
550  *cs = info->cipher_suite;
551 
552  return 0;
553 }
554 
555 int rtnl_link_macsec_set_icv_len(struct rtnl_link *link, uint16_t icv_len)
556 {
557  struct macsec_info *info = link->l_info;
558 
559  IS_MACSEC_LINK_ASSERT(link);
560 
561  if (icv_len > MACSEC_STD_ICV_LEN)
562  return -NLE_INVAL;
563 
564  info->icv_len = icv_len;
565  info->ce_mask |= MACSEC_ATTR_ICV_LEN;
566 
567  return 0;
568 }
569 
570 int rtnl_link_macsec_get_icv_len(struct rtnl_link *link, uint16_t *icv_len)
571 {
572  struct macsec_info *info = link->l_info;
573 
574  IS_MACSEC_LINK_ASSERT(link);
575 
576  if (!(info->ce_mask & MACSEC_ATTR_ICV_LEN))
577  return -NLE_NOATTR;
578 
579  if (icv_len)
580  *icv_len = info->icv_len;
581 
582  return 0;
583 }
584 
585 int rtnl_link_macsec_set_protect(struct rtnl_link *link, uint8_t protect)
586 {
587  struct macsec_info *info = link->l_info;
588 
589  IS_MACSEC_LINK_ASSERT(link);
590 
591  if (protect > 1)
592  return -NLE_INVAL;
593 
594  info->protect = protect;
595  info->ce_mask |= MACSEC_ATTR_PROTECT;
596 
597  return 0;
598 }
599 
600 int rtnl_link_macsec_get_protect(struct rtnl_link *link, uint8_t *protect)
601 {
602  struct macsec_info *info = link->l_info;
603 
604  IS_MACSEC_LINK_ASSERT(link);
605 
606  if (!(info->ce_mask & MACSEC_ATTR_PROTECT))
607  return -NLE_NOATTR;
608 
609  if (protect)
610  *protect = info->protect;
611 
612  return 0;
613 }
614 
615 int rtnl_link_macsec_set_encrypt(struct rtnl_link *link, uint8_t encrypt)
616 {
617  struct macsec_info *info = link->l_info;
618 
619  IS_MACSEC_LINK_ASSERT(link);
620 
621  if (encrypt > 1)
622  return -NLE_INVAL;
623 
624  info->encrypt = encrypt;
625  info->ce_mask |= MACSEC_ATTR_ENCRYPT;
626 
627  return 0;
628 }
629 
630 int rtnl_link_macsec_get_encrypt(struct rtnl_link *link, uint8_t *encrypt)
631 {
632  struct macsec_info *info = link->l_info;
633 
634  IS_MACSEC_LINK_ASSERT(link);
635 
636  if (!(info->ce_mask & MACSEC_ATTR_ENCRYPT))
637  return -NLE_NOATTR;
638 
639  if (encrypt)
640  *encrypt = info->encrypt;
641 
642  return 0;
643 }
644 
645 int rtnl_link_macsec_set_offload(struct rtnl_link *link, uint8_t offload)
646 {
647  struct macsec_info *info = link->l_info;
648 
649  IS_MACSEC_LINK_ASSERT(link);
650 
651  if (offload > 1)
652  return -NLE_INVAL;
653 
654  info->offload = offload;
655  info->ce_mask |= MACSEC_ATTR_OFFLOAD;
656 
657  return 0;
658 }
659 
660 int rtnl_link_macsec_get_offload(struct rtnl_link *link, uint8_t *offload)
661 {
662  struct macsec_info *info = link->l_info;
663 
664  IS_MACSEC_LINK_ASSERT(link);
665 
666  if (!(info->ce_mask & MACSEC_ATTR_OFFLOAD))
667  return -NLE_NOATTR;
668 
669  if (offload)
670  *offload = info->offload;
671 
672  return 0;
673 }
674 
675 int rtnl_link_macsec_set_encoding_sa(struct rtnl_link *link, uint8_t encoding_sa)
676 {
677  struct macsec_info *info = link->l_info;
678 
679  IS_MACSEC_LINK_ASSERT(link);
680 
681  if (encoding_sa > 3)
682  return -NLE_INVAL;
683 
684  info->encoding_sa = encoding_sa;
685  info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
686 
687  return 0;
688 }
689 
690 int rtnl_link_macsec_get_encoding_sa(struct rtnl_link *link, uint8_t *encoding_sa)
691 {
692  struct macsec_info *info = link->l_info;
693 
694  IS_MACSEC_LINK_ASSERT(link);
695 
696  if (!(info->ce_mask & MACSEC_ATTR_ENCODING_SA))
697  return -NLE_NOATTR;
698 
699  if (encoding_sa)
700  *encoding_sa = info->encoding_sa;
701 
702  return 0;
703 }
704 
705 int rtnl_link_macsec_set_validation_type(struct rtnl_link *link, enum macsec_validation_type validate)
706 {
707  struct macsec_info *info = link->l_info;
708 
709  IS_MACSEC_LINK_ASSERT(link);
710 
711  if (validate > MACSEC_VALIDATE_MAX)
712  return -NLE_INVAL;
713 
714  info->validate = validate;
715  info->ce_mask |= MACSEC_ATTR_VALIDATION;
716 
717  return 0;
718 }
719 
720 int rtnl_link_macsec_get_validation_type(struct rtnl_link *link, enum macsec_validation_type *validate)
721 {
722  struct macsec_info *info = link->l_info;
723 
724  IS_MACSEC_LINK_ASSERT(link);
725 
726  if (!(info->ce_mask & MACSEC_ATTR_VALIDATION))
727  return -NLE_NOATTR;
728 
729  if (validate)
730  *validate = info->validate;
731 
732  return 0;
733 }
734 
735 int rtnl_link_macsec_set_replay_protect(struct rtnl_link *link, uint8_t replay_protect)
736 {
737  struct macsec_info *info = link->l_info;
738 
739  IS_MACSEC_LINK_ASSERT(link);
740 
741  if (replay_protect > 1)
742  return -NLE_INVAL;
743 
744  info->replay_protect = replay_protect;
745  info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
746 
747  return 0;
748 }
749 
750 int rtnl_link_macsec_get_replay_protect(struct rtnl_link *link, uint8_t *replay_protect)
751 {
752  struct macsec_info *info = link->l_info;
753 
754  IS_MACSEC_LINK_ASSERT(link);
755 
756  if (!(info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT))
757  return -NLE_NOATTR;
758 
759  if (replay_protect)
760  *replay_protect = info->replay_protect;
761 
762  return 0;
763 }
764 
765 int rtnl_link_macsec_set_window(struct rtnl_link *link, uint32_t window)
766 {
767  struct macsec_info *info = link->l_info;
768 
769  IS_MACSEC_LINK_ASSERT(link);
770 
771  info->window = window;
772  info->ce_mask |= MACSEC_ATTR_WINDOW;
773 
774  return 0;
775 }
776 
777 int rtnl_link_macsec_get_window(struct rtnl_link *link, uint32_t *window)
778 {
779  struct macsec_info *info = link->l_info;
780 
781  IS_MACSEC_LINK_ASSERT(link);
782 
783  if (!(info->ce_mask & MACSEC_ATTR_WINDOW))
784  return -NLE_NOATTR;
785 
786  if (window)
787  *window = info->window;
788 
789  return 0;
790 }
791 
792 int rtnl_link_macsec_set_send_sci(struct rtnl_link *link, uint8_t send_sci)
793 {
794  struct macsec_info *info = link->l_info;
795 
796  IS_MACSEC_LINK_ASSERT(link);
797 
798  if (send_sci > 1)
799  return -NLE_INVAL;
800 
801  info->send_sci = send_sci;
802  info->ce_mask |= MACSEC_ATTR_INC_SCI;
803 
804  return 0;
805 }
806 
807 int rtnl_link_macsec_get_send_sci(struct rtnl_link *link, uint8_t *send_sci)
808 {
809  struct macsec_info *info = link->l_info;
810 
811  IS_MACSEC_LINK_ASSERT(link);
812 
813  if (!(info->ce_mask & MACSEC_ATTR_INC_SCI))
814  return -NLE_NOATTR;
815 
816  if (send_sci)
817  *send_sci = info->send_sci;
818 
819  return 0;
820 }
821 
822 int rtnl_link_macsec_set_end_station(struct rtnl_link *link, uint8_t end_station)
823 {
824  struct macsec_info *info = link->l_info;
825 
826  IS_MACSEC_LINK_ASSERT(link);
827 
828  if (end_station > 1)
829  return -NLE_INVAL;
830 
831  info->end_station = end_station;
832  info->ce_mask |= MACSEC_ATTR_ES;
833 
834  return 0;
835 }
836 
837 int rtnl_link_macsec_get_end_station(struct rtnl_link *link, uint8_t *es)
838 {
839  struct macsec_info *info = link->l_info;
840 
841  IS_MACSEC_LINK_ASSERT(link);
842 
843  if (!(info->ce_mask & MACSEC_ATTR_ES))
844  return -NLE_NOATTR;
845 
846  if (es)
847  *es = info->end_station;
848 
849  return 0;
850 }
851 
852 int rtnl_link_macsec_set_scb(struct rtnl_link *link, uint8_t scb)
853 {
854  struct macsec_info *info = link->l_info;
855 
856  IS_MACSEC_LINK_ASSERT(link);
857 
858  if (scb > 1)
859  return -NLE_INVAL;
860 
861  info->scb = scb;
862  info->ce_mask |= MACSEC_ATTR_SCB;
863 
864  return 0;
865 }
866 
867 int rtnl_link_macsec_get_scb(struct rtnl_link *link, uint8_t *scb)
868 {
869  struct macsec_info *info = link->l_info;
870 
871  IS_MACSEC_LINK_ASSERT(link);
872 
873  if (!(info->ce_mask & MACSEC_ATTR_SCB))
874  return -NLE_NOATTR;
875 
876  if (scb)
877  *scb = info->scb;
878 
879  return 0;
880 }
881 
882 /** @} */
883 
884 /** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
#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:754
#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:599
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
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:1013
#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:958
@ 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:452
int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
Get SCI.
Definition: macsec.c:472
int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
Set port identifier.
Definition: macsec.c:494
int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
Get port identifier.
Definition: macsec.c:513
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