libnl  3.4.0
macsec.c
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  */
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 
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 
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 
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 */
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 
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 
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 
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 
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 
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 
408 static void __init macsec_init(void)
409 {
410  rtnl_link_register_info(&macsec_info_ops);
411 }
412 
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 
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  */
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  */
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  */
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  */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 /** @} */
Dump object briefly on one line.
Definition: types.h:22
8 bit integer
Definition: attr.h:41
Attribute validation policy.
Definition: attr.h:69
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:606
#define NLA_PUT_U64(msg, attrtype, value)
Add 64 bit integer attribute to netlink message.
Definition: attr.h:253
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:199
int rtnl_link_macsec_get_sci(struct rtnl_link *link, uint64_t *sci)
Get SCI.
Definition: macsec.c:468
Dump all attributes but no statistics.
Definition: types.h:23
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:924
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:999
int rtnl_link_macsec_set_sci(struct rtnl_link *link, uint64_t sci)
Set SCI.
Definition: macsec.c:448
int rtnl_link_macsec_set_port(struct rtnl_link *link, uint16_t port)
Set port identifier.
Definition: macsec.c:490
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:235
int rtnl_link_macsec_get_port(struct rtnl_link *link, uint16_t *port)
Get port identifier.
Definition: macsec.c:509
64 bit integer
Definition: attr.h:44
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:217
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
Definition: attr.c:761
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:961
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:902