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