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