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