12 #include <netlink-private/netlink.h> 13 #include <netlink/netlink.h> 14 #include <netlink/attr.h> 15 #include <netlink/utils.h> 16 #include <netlink/object.h> 17 #include <netlink/route/rtnl.h> 18 #include <netlink-private/route/link/api.h> 19 #include <netlink-private/utils.h> 21 #include <linux/if_macsec.h> 23 #define MACSEC_ATTR_SCI (1 << 0) 24 #define MACSEC_ATTR_ICV_LEN (1 << 1) 25 #define MACSEC_ATTR_CIPHER_SUITE (1 << 2) 26 #define MACSEC_ATTR_WINDOW (1 << 3) 27 #define MACSEC_ATTR_ENCODING_SA (1 << 4) 28 #define MACSEC_ATTR_ENCRYPT (1 << 5) 29 #define MACSEC_ATTR_PROTECT (1 << 6) 30 #define MACSEC_ATTR_INC_SCI (1 << 7) 31 #define MACSEC_ATTR_ES (1 << 8) 32 #define MACSEC_ATTR_SCB (1 << 9) 33 #define MACSEC_ATTR_REPLAY_PROTECT (1 << 10) 34 #define MACSEC_ATTR_VALIDATION (1 << 11) 35 #define MACSEC_ATTR_PORT (1 << 12) 41 uint64_t cipher_suite;
44 enum macsec_validation_type validate;
47 uint8_t send_sci, end_station, scb, replay_protect, protect, encrypt;
52 static struct nla_policy macsec_policy[IFLA_MACSEC_MAX+1] = {
54 [IFLA_MACSEC_ICV_LEN] = { .type =
NLA_U8 },
55 [IFLA_MACSEC_CIPHER_SUITE] = { .type =
NLA_U64 },
56 [IFLA_MACSEC_WINDOW] = { .type =
NLA_U32 },
57 [IFLA_MACSEC_ENCODING_SA] = { .type =
NLA_U8 },
58 [IFLA_MACSEC_ENCRYPT] = { .type =
NLA_U8 },
59 [IFLA_MACSEC_PROTECT] = { .type =
NLA_U8 },
60 [IFLA_MACSEC_INC_SCI] = { .type =
NLA_U8 },
61 [IFLA_MACSEC_ES] = { .type =
NLA_U8 },
62 [IFLA_MACSEC_SCB] = { .type =
NLA_U8 },
63 [IFLA_MACSEC_REPLAY_PROTECT] = { .type =
NLA_U8 },
64 [IFLA_MACSEC_VALIDATION] = { .type =
NLA_U8 },
67 #define DEFAULT_ICV_LEN 16 69 static int macsec_alloc(
struct rtnl_link *link)
79 memset(link->l_info, 0,
sizeof(
struct macsec_info));
82 info->cipher_suite = MACSEC_DEFAULT_CIPHER_ID;
83 info->icv_len = DEFAULT_ICV_LEN;
84 info->ce_mask = MACSEC_ATTR_CIPHER_SUITE | MACSEC_ATTR_ICV_LEN;
89 static int macsec_parse(
struct rtnl_link *link,
struct nlattr *data,
90 struct nlattr *xstats)
92 struct nlattr *tb[IFLA_MACSEC_MAX+1];
96 NL_DBG(3,
"Parsing MACsec link info\n");
101 if ((err = macsec_alloc(link)) < 0)
106 if (tb[IFLA_MACSEC_SCI]) {
107 info->sci = ntohll(
nla_get_u64(tb[IFLA_MACSEC_SCI]));
108 info->ce_mask |= MACSEC_ATTR_SCI;
111 if (tb[IFLA_MACSEC_PROTECT]) {
112 info->protect =
nla_get_u8(tb[IFLA_MACSEC_PROTECT]);
113 info->ce_mask |= MACSEC_ATTR_PROTECT;
116 if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
117 info->cipher_suite =
nla_get_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
118 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
121 if (tb[IFLA_MACSEC_ICV_LEN]) {
122 info->icv_len =
nla_get_u8(tb[IFLA_MACSEC_ICV_LEN]);
123 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
126 if (tb[IFLA_MACSEC_ENCODING_SA]) {
127 info->encoding_sa =
nla_get_u8(tb[IFLA_MACSEC_ENCODING_SA]);
128 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
131 if (tb[IFLA_MACSEC_VALIDATION]) {
132 info->validate =
nla_get_u8(tb[IFLA_MACSEC_VALIDATION]);
133 info->ce_mask |= MACSEC_ATTR_VALIDATION;
136 if (tb[IFLA_MACSEC_ENCRYPT]) {
137 info->encrypt =
nla_get_u8(tb[IFLA_MACSEC_ENCRYPT]);
138 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
141 if (tb[IFLA_MACSEC_INC_SCI]) {
142 info->send_sci =
nla_get_u8(tb[IFLA_MACSEC_INC_SCI]);
143 info->ce_mask |= MACSEC_ATTR_INC_SCI;
146 if (tb[IFLA_MACSEC_ES]) {
147 info->end_station =
nla_get_u8(tb[IFLA_MACSEC_ES]);
148 info->ce_mask |= MACSEC_ATTR_ES;
151 if (tb[IFLA_MACSEC_SCB]) {
153 info->ce_mask |= MACSEC_ATTR_SCB;
156 if (tb[IFLA_MACSEC_REPLAY_PROTECT]) {
157 info->replay_protect =
nla_get_u8(tb[IFLA_MACSEC_REPLAY_PROTECT]);
158 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
161 if (tb[IFLA_MACSEC_WINDOW]) {
162 info->window =
nla_get_u32(tb[IFLA_MACSEC_WINDOW]);
163 info->ce_mask |= MACSEC_ATTR_WINDOW;
171 static void macsec_free(
struct rtnl_link *link)
177 static const char *values_on_off[] = {
"off",
"on" };
179 static const char *VALIDATE_STR[] = {
180 [MACSEC_VALIDATE_DISABLED] =
"disabled",
181 [MACSEC_VALIDATE_CHECK] =
"check",
182 [MACSEC_VALIDATE_STRICT] =
"strict",
185 static char *replay_protect_str(
char *buf, uint8_t replay_protect, uint8_t window)
187 if (replay_protect == 1) {
188 sprintf(buf,
"replay_protect on window %d", window);
189 }
else if (replay_protect == 0) {
190 sprintf(buf,
"replay_protect off");
198 #define PRINT_FLAG(buf, i, field, c) ({ if (i->field == 1) *buf++ = c; }) 199 static char *flags_str(
char *buf,
unsigned char len,
struct macsec_info *info)
204 PRINT_FLAG(tmp, info, protect,
'P');
205 PRINT_FLAG(tmp, info, encrypt,
'E');
206 PRINT_FLAG(tmp, info, send_sci,
'S');
207 PRINT_FLAG(tmp, info, end_station,
'e');
208 PRINT_FLAG(tmp, info, scb,
's');
209 PRINT_FLAG(tmp, info, replay_protect,
'R');
213 switch (info->validate) {
214 case MACSEC_VALIDATE_DISABLED:
217 case MACSEC_VALIDATE_CHECK:
220 case MACSEC_VALIDATE_STRICT:
227 sprintf(tmp,
" %d", info->encoding_sa);
237 nl_dump(p,
"sci %016llx <%s>", info->sci, flags_str(tmp,
sizeof(tmp), info));
245 nl_dump(p,
" sci %016llx protect %s encoding_sa %d encrypt %s send_sci %s validate %s %s\n",
246 info->sci, values_on_off[info->protect], info->encoding_sa, values_on_off[info->encrypt], values_on_off[info->send_sci],
247 VALIDATE_STR[info->validate],
248 replay_protect_str(tmp, info->replay_protect, info->window));
249 nl_dump(p,
" cipher suite: %016llx, icv_len %d\n",
250 info->cipher_suite, info->icv_len);
271 static int macsec_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
279 if (info->ce_mask & MACSEC_ATTR_SCI)
280 NLA_PUT_U64(msg, IFLA_MACSEC_SCI, htonll(info->sci));
281 else if (info->ce_mask & MACSEC_ATTR_PORT)
282 NLA_PUT_U16(msg, IFLA_MACSEC_PORT, htons(info->port));
284 if ((info->ce_mask & MACSEC_ATTR_ENCRYPT))
285 NLA_PUT_U8(msg, IFLA_MACSEC_ENCRYPT, info->encrypt);
287 if (info->cipher_suite != MACSEC_DEFAULT_CIPHER_ID || info->icv_len != DEFAULT_ICV_LEN) {
288 NLA_PUT_U64(msg, IFLA_MACSEC_CIPHER_SUITE, info->cipher_suite);
289 NLA_PUT_U8(msg, IFLA_MACSEC_ICV_LEN, info->icv_len);
292 if ((info->ce_mask & MACSEC_ATTR_INC_SCI))
293 NLA_PUT_U8(msg, IFLA_MACSEC_INC_SCI, info->send_sci);
295 if ((info->ce_mask & MACSEC_ATTR_ES))
296 NLA_PUT_U8(msg, IFLA_MACSEC_ES, info->end_station);
298 if ((info->ce_mask & MACSEC_ATTR_SCB))
301 if ((info->ce_mask & MACSEC_ATTR_PROTECT))
302 NLA_PUT_U8(msg, IFLA_MACSEC_PROTECT, info->protect);
304 if ((info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT)) {
305 if (info->replay_protect && !(info->ce_mask & MACSEC_ATTR_WINDOW))
308 NLA_PUT_U8(msg, IFLA_MACSEC_REPLAY_PROTECT, info->replay_protect);
309 NLA_PUT_U32(msg, IFLA_MACSEC_WINDOW, info->window);
312 if ((info->ce_mask & MACSEC_ATTR_VALIDATION))
313 NLA_PUT_U8(msg, IFLA_MACSEC_VALIDATION, info->validate);
315 if ((info->ce_mask & MACSEC_ATTR_ENCODING_SA))
316 NLA_PUT_U8(msg, IFLA_MACSEC_ENCODING_SA, info->encoding_sa);
332 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
334 #define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR) 336 if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
337 diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
338 else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
339 diff |= MACSEC_DIFF(PORT, a->port != b->port);
341 if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
342 diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
343 diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
346 if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
347 int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
348 if (a->replay_protect && b->replay_protect)
349 d |= MACSEC_DIFF(WINDOW, a->window != b->window);
353 diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
354 diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
355 diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
356 diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
357 diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
358 diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
359 diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
366 static struct rtnl_link_info_ops macsec_info_ops = {
368 .io_alloc = macsec_alloc,
369 .io_parse = macsec_parse,
374 .io_clone = macsec_clone,
375 .io_put_attrs = macsec_put_attrs,
376 .io_free = macsec_free,
377 .io_compare = macsec_compare,
380 static void __init macsec_init(
void)
385 static void __exit macsec_exit(
void)
390 #define IS_MACSEC_LINK_ASSERT(link) \ 391 if ((link)->l_info_ops != &macsec_info_ops) { \ 392 APPBUG("Link is not a MACsec link. set type \"macsec\" first."); \ 393 return -NLE_OPNOTSUPP; \ 396 struct rtnl_link *rtnl_link_macsec_alloc(
void)
411 int rtnl_link_macsec_set_sci(
struct rtnl_link *link, uint64_t sci)
415 IS_MACSEC_LINK_ASSERT(link);
418 info->ce_mask |= MACSEC_ATTR_SCI;
423 int rtnl_link_macsec_get_sci(
struct rtnl_link *link, uint64_t *sci)
427 IS_MACSEC_LINK_ASSERT(link);
429 if (!(info->ce_mask & MACSEC_ATTR_SCI))
438 int rtnl_link_macsec_set_port(
struct rtnl_link *link, uint16_t port)
442 IS_MACSEC_LINK_ASSERT(link);
445 info->ce_mask |= MACSEC_ATTR_PORT;
450 int rtnl_link_macsec_get_port(
struct rtnl_link *link, uint16_t *port)
454 IS_MACSEC_LINK_ASSERT(link);
456 if (!(info->ce_mask & MACSEC_ATTR_PORT))
465 int rtnl_link_macsec_set_cipher_suite(
struct rtnl_link *link, uint64_t cipher_suite)
469 IS_MACSEC_LINK_ASSERT(link);
471 info->cipher_suite = cipher_suite;
472 info->ce_mask |= MACSEC_ATTR_CIPHER_SUITE;
477 int rtnl_link_macsec_get_cipher_suite(
struct rtnl_link *link, uint64_t *cs)
481 IS_MACSEC_LINK_ASSERT(link);
483 if (!(info->ce_mask & MACSEC_ATTR_CIPHER_SUITE))
487 *cs = info->cipher_suite;
492 int rtnl_link_macsec_set_icv_len(
struct rtnl_link *link, uint16_t icv_len)
496 IS_MACSEC_LINK_ASSERT(link);
498 if (icv_len > MACSEC_STD_ICV_LEN)
501 info->icv_len = icv_len;
502 info->ce_mask |= MACSEC_ATTR_ICV_LEN;
507 int rtnl_link_macsec_get_icv_len(
struct rtnl_link *link, uint16_t *icv_len)
511 IS_MACSEC_LINK_ASSERT(link);
513 if (!(info->ce_mask & MACSEC_ATTR_ICV_LEN))
517 *icv_len = info->icv_len;
522 int rtnl_link_macsec_set_protect(
struct rtnl_link *link, uint8_t protect)
526 IS_MACSEC_LINK_ASSERT(link);
531 info->protect = protect;
532 info->ce_mask |= MACSEC_ATTR_PROTECT;
537 int rtnl_link_macsec_get_protect(
struct rtnl_link *link, uint8_t *protect)
541 IS_MACSEC_LINK_ASSERT(link);
543 if (!(info->ce_mask & MACSEC_ATTR_PROTECT))
547 *protect = info->protect;
552 int rtnl_link_macsec_set_encrypt(
struct rtnl_link *link, uint8_t encrypt)
556 IS_MACSEC_LINK_ASSERT(link);
561 info->encrypt = encrypt;
562 info->ce_mask |= MACSEC_ATTR_ENCRYPT;
567 int rtnl_link_macsec_get_encrypt(
struct rtnl_link *link, uint8_t *encrypt)
571 IS_MACSEC_LINK_ASSERT(link);
573 if (!(info->ce_mask & MACSEC_ATTR_ENCRYPT))
577 *encrypt = info->encrypt;
582 int rtnl_link_macsec_set_encoding_sa(
struct rtnl_link *link, uint8_t encoding_sa)
586 IS_MACSEC_LINK_ASSERT(link);
591 info->encoding_sa = encoding_sa;
592 info->ce_mask |= MACSEC_ATTR_ENCODING_SA;
597 int rtnl_link_macsec_get_encoding_sa(
struct rtnl_link *link, uint8_t *encoding_sa)
601 IS_MACSEC_LINK_ASSERT(link);
603 if (!(info->ce_mask & MACSEC_ATTR_ENCODING_SA))
607 *encoding_sa = info->encoding_sa;
612 int rtnl_link_macsec_set_validation_type(
struct rtnl_link *link,
enum macsec_validation_type validate)
616 IS_MACSEC_LINK_ASSERT(link);
621 info->validate = validate;
622 info->ce_mask |= MACSEC_ATTR_VALIDATION;
627 int rtnl_link_macsec_get_validation_type(
struct rtnl_link *link,
enum macsec_validation_type *validate)
631 IS_MACSEC_LINK_ASSERT(link);
633 if (!(info->ce_mask & MACSEC_ATTR_VALIDATION))
637 *validate = info->validate;
642 int rtnl_link_macsec_set_replay_protect(
struct rtnl_link *link, uint8_t replay_protect)
646 IS_MACSEC_LINK_ASSERT(link);
648 if (replay_protect > 1)
651 info->replay_protect = replay_protect;
652 info->ce_mask |= MACSEC_ATTR_REPLAY_PROTECT;
657 int rtnl_link_macsec_get_replay_protect(
struct rtnl_link *link, uint8_t *replay_protect)
661 IS_MACSEC_LINK_ASSERT(link);
663 if (!(info->ce_mask & MACSEC_ATTR_REPLAY_PROTECT))
667 *replay_protect = info->replay_protect;
672 int rtnl_link_macsec_set_window(
struct rtnl_link *link, uint32_t window)
676 IS_MACSEC_LINK_ASSERT(link);
678 info->window = window;
679 info->ce_mask |= MACSEC_ATTR_WINDOW;
684 int rtnl_link_macsec_get_window(
struct rtnl_link *link, uint32_t *window)
688 IS_MACSEC_LINK_ASSERT(link);
690 if (!(info->ce_mask & MACSEC_ATTR_WINDOW))
694 *window = info->window;
699 int rtnl_link_macsec_set_send_sci(
struct rtnl_link *link, uint8_t send_sci)
703 IS_MACSEC_LINK_ASSERT(link);
708 info->send_sci = send_sci;
709 info->ce_mask |= MACSEC_ATTR_INC_SCI;
714 int rtnl_link_macsec_get_send_sci(
struct rtnl_link *link, uint8_t *send_sci)
718 IS_MACSEC_LINK_ASSERT(link);
720 if (!(info->ce_mask & MACSEC_ATTR_INC_SCI))
724 *send_sci = info->send_sci;
729 int rtnl_link_macsec_set_end_station(
struct rtnl_link *link, uint8_t end_station)
733 IS_MACSEC_LINK_ASSERT(link);
738 info->end_station = end_station;
739 info->ce_mask |= MACSEC_ATTR_ES;
744 int rtnl_link_macsec_get_end_station(
struct rtnl_link *link, uint8_t *es)
748 IS_MACSEC_LINK_ASSERT(link);
750 if (!(info->ce_mask & MACSEC_ATTR_ES))
754 *es = info->end_station;
759 int rtnl_link_macsec_set_scb(
struct rtnl_link *link, uint8_t scb)
763 IS_MACSEC_LINK_ASSERT(link);
769 info->ce_mask |= MACSEC_ATTR_SCB;
774 int rtnl_link_macsec_get_scb(
struct rtnl_link *link, uint8_t *scb)
778 IS_MACSEC_LINK_ASSERT(link);
780 if (!(info->ce_mask & MACSEC_ATTR_SCB))
Dump object briefly on one line.
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
Attribute validation policy.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
#define NLA_PUT_U64(msg, attrtype, value)
Add 64 bit integer attribute to netlink message.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Dump all attributes but no statistics.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
uint16_t type
Type of attribute or NLA_UNSPEC.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.