1 /*
2 * Driver interaction with Linux MACsec kernel module
3 * Copyright (c) 2016, Sabrina Dubroca <sd@queasysnail.net> and Red Hat, Inc.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <sys/ioctl.h>
11 #include <net/if.h>
12 #include <netpacket/packet.h>
13 #include <net/if_arp.h>
14 #include <net/if.h>
15 #include <netlink/netlink.h>
16 #include <netlink/genl/genl.h>
17 #include <netlink/genl/ctrl.h>
18 #include <netlink/route/link.h>
19 #include <netlink/route/link/macsec.h>
20 #include <linux/if_macsec.h>
21 #include <inttypes.h>
22
23 #include "utils/common.h"
24 #include "utils/eloop.h"
25 #include "pae/ieee802_1x_kay.h"
26 #include "driver.h"
27 #include "driver_wired_common.h"
28
29 #define DRV_PREFIX "macsec_linux: "
30
31 #define UNUSED_SCI 0xffffffffffffffff
32
33 struct cb_arg {
34 struct macsec_drv_data *drv;
35 u32 *pn;
36 int ifindex;
37 u8 txsa;
38 u8 rxsa;
39 u64 rxsci;
40 };
41
42 struct macsec_genl_ctx {
43 struct nl_sock *sk;
44 int macsec_genl_id;
45 struct cb_arg cb_arg;
46 };
47
48 struct macsec_drv_data {
49 struct driver_wired_common_data common;
50 struct rtnl_link *link;
51 struct nl_cache *link_cache;
52 struct nl_sock *sk;
53 struct macsec_genl_ctx ctx;
54
55 struct netlink_data *netlink;
56 struct nl_handle *nl;
57 char ifname[IFNAMSIZ + 1];
58 int ifi;
59 int parent_ifi;
60
61 Boolean created_link;
62
63 Boolean controlled_port_enabled;
64 Boolean controlled_port_enabled_set;
65
66 Boolean protect_frames;
67 Boolean protect_frames_set;
68
69 Boolean encrypt;
70 Boolean encrypt_set;
71
72 Boolean replay_protect;
73 Boolean replay_protect_set;
74
75 u32 replay_window;
76
77 u8 encoding_sa;
78 Boolean encoding_sa_set;
79 };
80
81
82 static int dump_callback(struct nl_msg *msg, void *argp);
83
84
msg_prepare(enum macsec_nl_commands cmd,const struct macsec_genl_ctx * ctx,unsigned int ifindex)85 static struct nl_msg * msg_prepare(enum macsec_nl_commands cmd,
86 const struct macsec_genl_ctx *ctx,
87 unsigned int ifindex)
88 {
89 struct nl_msg *msg;
90
91 msg = nlmsg_alloc();
92 if (!msg) {
93 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc message");
94 return NULL;
95 }
96
97 if (!genlmsg_put(msg, 0, 0, ctx->macsec_genl_id, 0, 0, cmd, 0)) {
98 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to put header");
99 goto nla_put_failure;
100 }
101
102 NLA_PUT_U32(msg, MACSEC_ATTR_IFINDEX, ifindex);
103
104 return msg;
105
106 nla_put_failure:
107 nlmsg_free(msg);
108 return NULL;
109 }
110
111
nla_put_rxsc_config(struct nl_msg * msg,u64 sci)112 static int nla_put_rxsc_config(struct nl_msg *msg, u64 sci)
113 {
114 struct nlattr *nest = nla_nest_start(msg, MACSEC_ATTR_RXSC_CONFIG);
115
116 if (!nest)
117 return -1;
118
119 NLA_PUT_U64(msg, MACSEC_RXSC_ATTR_SCI, sci);
120
121 nla_nest_end(msg, nest);
122
123 return 0;
124
125 nla_put_failure:
126 return -1;
127 }
128
129
init_genl_ctx(struct macsec_drv_data * drv)130 static int init_genl_ctx(struct macsec_drv_data *drv)
131 {
132 struct macsec_genl_ctx *ctx = &drv->ctx;
133
134 ctx->sk = nl_socket_alloc();
135 if (!ctx->sk) {
136 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc genl socket");
137 return -1;
138 }
139
140 if (genl_connect(ctx->sk) < 0) {
141 wpa_printf(MSG_ERROR,
142 DRV_PREFIX "connection to genl socket failed");
143 goto out_free;
144 }
145
146 ctx->macsec_genl_id = genl_ctrl_resolve(ctx->sk, "macsec");
147 if (ctx->macsec_genl_id < 0) {
148 wpa_printf(MSG_ERROR, DRV_PREFIX "genl resolve failed");
149 goto out_free;
150 }
151
152 memset(&ctx->cb_arg, 0, sizeof(ctx->cb_arg));
153 ctx->cb_arg.drv = drv;
154
155 nl_socket_modify_cb(ctx->sk, NL_CB_VALID, NL_CB_CUSTOM, dump_callback,
156 &ctx->cb_arg);
157
158 return 0;
159
160 out_free:
161 nl_socket_free(ctx->sk);
162 ctx->sk = NULL;
163 return -1;
164 }
165
166
try_commit(struct macsec_drv_data * drv)167 static int try_commit(struct macsec_drv_data *drv)
168 {
169 int err;
170
171 if (!drv->sk)
172 return 0;
173
174 if (!drv->link)
175 return 0;
176
177 if (drv->controlled_port_enabled_set) {
178 struct rtnl_link *change = rtnl_link_alloc();
179
180 wpa_printf(MSG_DEBUG, DRV_PREFIX
181 "%s: try_commit controlled_port_enabled=%d",
182 drv->ifname, drv->controlled_port_enabled);
183 if (!change)
184 return -1;
185
186 rtnl_link_set_name(change, drv->ifname);
187
188 if (drv->controlled_port_enabled)
189 rtnl_link_set_flags(change, IFF_UP);
190 else
191 rtnl_link_unset_flags(change, IFF_UP);
192
193 err = rtnl_link_change(drv->sk, change, change, 0);
194 if (err < 0)
195 return err;
196
197 rtnl_link_put(change);
198
199 drv->controlled_port_enabled_set = FALSE;
200 }
201
202 if (drv->protect_frames_set) {
203 wpa_printf(MSG_DEBUG, DRV_PREFIX
204 "%s: try_commit protect_frames=%d",
205 drv->ifname, drv->protect_frames);
206 rtnl_link_macsec_set_protect(drv->link, drv->protect_frames);
207 }
208
209 if (drv->encrypt_set) {
210 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: try_commit encrypt=%d",
211 drv->ifname, drv->encrypt);
212 rtnl_link_macsec_set_encrypt(drv->link, drv->encrypt);
213 }
214
215 if (drv->replay_protect_set) {
216 wpa_printf(MSG_DEBUG, DRV_PREFIX
217 "%s: try_commit replay_protect=%d replay_window=%d",
218 drv->ifname, drv->replay_protect,
219 drv->replay_window);
220 rtnl_link_macsec_set_replay_protect(drv->link,
221 drv->replay_protect);
222 if (drv->replay_protect)
223 rtnl_link_macsec_set_window(drv->link,
224 drv->replay_window);
225 }
226
227 if (drv->encoding_sa_set) {
228 wpa_printf(MSG_DEBUG, DRV_PREFIX
229 "%s: try_commit encoding_sa=%d",
230 drv->ifname, drv->encoding_sa);
231 rtnl_link_macsec_set_encoding_sa(drv->link, drv->encoding_sa);
232 }
233
234 err = rtnl_link_add(drv->sk, drv->link, 0);
235 if (err < 0)
236 return err;
237
238 drv->protect_frames_set = FALSE;
239 drv->encrypt_set = FALSE;
240 drv->replay_protect_set = FALSE;
241
242 return 0;
243 }
244
245
macsec_drv_wpa_deinit(void * priv)246 static void macsec_drv_wpa_deinit(void *priv)
247 {
248 struct macsec_drv_data *drv = priv;
249
250 driver_wired_deinit_common(&drv->common);
251 os_free(drv);
252 }
253
254
macsec_check_macsec(void)255 static int macsec_check_macsec(void)
256 {
257 struct nl_sock *sk;
258 int err = -1;
259
260 sk = nl_socket_alloc();
261 if (!sk) {
262 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to alloc genl socket");
263 return -1;
264 }
265
266 if (genl_connect(sk) < 0) {
267 wpa_printf(MSG_ERROR,
268 DRV_PREFIX "connection to genl socket failed");
269 goto out_free;
270 }
271
272 if (genl_ctrl_resolve(sk, "macsec") < 0) {
273 wpa_printf(MSG_ERROR,
274 DRV_PREFIX "genl resolve failed - macsec kernel module not present?");
275 goto out_free;
276 }
277
278 err = 0;
279
280 out_free:
281 nl_socket_free(sk);
282 return err;
283 }
284
285
macsec_drv_wpa_init(void * ctx,const char * ifname)286 static void * macsec_drv_wpa_init(void *ctx, const char *ifname)
287 {
288 struct macsec_drv_data *drv;
289
290 if (macsec_check_macsec() < 0)
291 return NULL;
292
293 drv = os_zalloc(sizeof(*drv));
294 if (!drv)
295 return NULL;
296
297 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
298 os_free(drv);
299 return NULL;
300 }
301
302 return drv;
303 }
304
305
macsec_drv_macsec_init(void * priv,struct macsec_init_params * params)306 static int macsec_drv_macsec_init(void *priv, struct macsec_init_params *params)
307 {
308 struct macsec_drv_data *drv = priv;
309 int err;
310
311 wpa_printf(MSG_DEBUG, "%s", __func__);
312
313 drv->sk = nl_socket_alloc();
314 if (!drv->sk)
315 return -1;
316
317 err = nl_connect(drv->sk, NETLINK_ROUTE);
318 if (err < 0) {
319 wpa_printf(MSG_ERROR, DRV_PREFIX
320 "Unable to connect NETLINK_ROUTE socket: %s",
321 strerror(errno));
322 goto sock;
323 }
324
325 err = rtnl_link_alloc_cache(drv->sk, AF_UNSPEC, &drv->link_cache);
326 if (err < 0) {
327 wpa_printf(MSG_ERROR, DRV_PREFIX "Unable to get link cache: %s",
328 strerror(errno));
329 goto sock;
330 }
331
332 drv->parent_ifi = rtnl_link_name2i(drv->link_cache, drv->common.ifname);
333 if (drv->parent_ifi == 0) {
334 wpa_printf(MSG_ERROR, DRV_PREFIX
335 "couldn't find ifindex for interface %s",
336 drv->common.ifname);
337 goto cache;
338 }
339 wpa_printf(MSG_DEBUG, DRV_PREFIX "ifname=%s parent_ifi=%d",
340 drv->common.ifname, drv->parent_ifi);
341
342 err = init_genl_ctx(drv);
343 if (err < 0)
344 goto cache;
345
346 return 0;
347
348 cache:
349 nl_cache_free(drv->link_cache);
350 drv->link_cache = NULL;
351 sock:
352 nl_socket_free(drv->sk);
353 drv->sk = NULL;
354 return -1;
355 }
356
357
macsec_drv_macsec_deinit(void * priv)358 static int macsec_drv_macsec_deinit(void *priv)
359 {
360 struct macsec_drv_data *drv = priv;
361
362 wpa_printf(MSG_DEBUG, "%s", __func__);
363
364 if (drv->sk)
365 nl_socket_free(drv->sk);
366 drv->sk = NULL;
367
368 if (drv->link_cache)
369 nl_cache_free(drv->link_cache);
370 drv->link_cache = NULL;
371
372 if (drv->ctx.sk)
373 nl_socket_free(drv->ctx.sk);
374
375 return 0;
376 }
377
378
macsec_drv_get_capability(void * priv,enum macsec_cap * cap)379 static int macsec_drv_get_capability(void *priv, enum macsec_cap *cap)
380 {
381 wpa_printf(MSG_DEBUG, "%s", __func__);
382
383 *cap = MACSEC_CAP_INTEG_AND_CONF;
384
385 return 0;
386 }
387
388
389 /**
390 * macsec_drv_enable_protect_frames - Set protect frames status
391 * @priv: Private driver interface data
392 * @enabled: TRUE = protect frames enabled
393 * FALSE = protect frames disabled
394 * Returns: 0 on success, -1 on failure (or if not supported)
395 */
macsec_drv_enable_protect_frames(void * priv,Boolean enabled)396 static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled)
397 {
398 struct macsec_drv_data *drv = priv;
399
400 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
401
402 drv->protect_frames_set = TRUE;
403 drv->protect_frames = enabled;
404
405 return try_commit(drv);
406 }
407
408
409 /**
410 * macsec_drv_enable_encrypt - Set protect frames status
411 * @priv: Private driver interface data
412 * @enabled: TRUE = protect frames enabled
413 * FALSE = protect frames disabled
414 * Returns: 0 on success, -1 on failure (or if not supported)
415 */
macsec_drv_enable_encrypt(void * priv,Boolean enabled)416 static int macsec_drv_enable_encrypt(void *priv, Boolean enabled)
417 {
418 struct macsec_drv_data *drv = priv;
419
420 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
421
422 drv->encrypt_set = TRUE;
423 drv->encrypt = enabled;
424
425 return try_commit(drv);
426 }
427
428
429 /**
430 * macsec_drv_set_replay_protect - Set replay protect status and window size
431 * @priv: Private driver interface data
432 * @enabled: TRUE = replay protect enabled
433 * FALSE = replay protect disabled
434 * @window: replay window size, valid only when replay protect enabled
435 * Returns: 0 on success, -1 on failure (or if not supported)
436 */
macsec_drv_set_replay_protect(void * priv,Boolean enabled,u32 window)437 static int macsec_drv_set_replay_protect(void *priv, Boolean enabled,
438 u32 window)
439 {
440 struct macsec_drv_data *drv = priv;
441
442 wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__,
443 enabled ? "TRUE" : "FALSE", window);
444
445 drv->replay_protect_set = TRUE;
446 drv->replay_protect = enabled;
447 if (enabled)
448 drv->replay_window = window;
449
450 return try_commit(drv);
451 }
452
453
454 /**
455 * macsec_drv_set_current_cipher_suite - Set current cipher suite
456 * @priv: Private driver interface data
457 * @cs: EUI64 identifier
458 * Returns: 0 on success, -1 on failure (or if not supported)
459 */
macsec_drv_set_current_cipher_suite(void * priv,u64 cs)460 static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs)
461 {
462 wpa_printf(MSG_DEBUG, "%s -> %016" PRIx64, __func__, cs);
463 return 0;
464 }
465
466
467 /**
468 * macsec_drv_enable_controlled_port - Set controlled port status
469 * @priv: Private driver interface data
470 * @enabled: TRUE = controlled port enabled
471 * FALSE = controlled port disabled
472 * Returns: 0 on success, -1 on failure (or if not supported)
473 */
macsec_drv_enable_controlled_port(void * priv,Boolean enabled)474 static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled)
475 {
476 struct macsec_drv_data *drv = priv;
477
478 wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE");
479
480 drv->controlled_port_enabled = enabled;
481 drv->controlled_port_enabled_set = TRUE;
482
483 return try_commit(drv);
484 }
485
486
487 static struct nla_policy sa_policy[MACSEC_SA_ATTR_MAX + 1] = {
488 [MACSEC_SA_ATTR_AN] = { .type = NLA_U8 },
489 [MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 },
490 [MACSEC_SA_ATTR_PN] = { .type = NLA_U32 },
491 [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY },
492 };
493
494 static struct nla_policy sc_policy[MACSEC_RXSC_ATTR_MAX + 1] = {
495 [MACSEC_RXSC_ATTR_SCI] = { .type = NLA_U64 },
496 [MACSEC_RXSC_ATTR_ACTIVE] = { .type = NLA_U8 },
497 [MACSEC_RXSC_ATTR_SA_LIST] = { .type = NLA_NESTED },
498 };
499
500 static struct nla_policy main_policy[MACSEC_ATTR_MAX + 1] = {
501 [MACSEC_ATTR_IFINDEX] = { .type = NLA_U32 },
502 [MACSEC_ATTR_SECY] = { .type = NLA_NESTED },
503 [MACSEC_ATTR_TXSA_LIST] = { .type = NLA_NESTED },
504 [MACSEC_ATTR_RXSC_LIST] = { .type = NLA_NESTED },
505 };
506
dump_callback(struct nl_msg * msg,void * argp)507 static int dump_callback(struct nl_msg *msg, void *argp)
508 {
509 struct nlmsghdr *ret_hdr = nlmsg_hdr(msg);
510 struct nlattr *tb_msg[MACSEC_ATTR_MAX + 1];
511 struct cb_arg *arg = (struct cb_arg *) argp;
512 struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(ret_hdr);
513 int err;
514
515 if (ret_hdr->nlmsg_type != arg->drv->ctx.macsec_genl_id)
516 return 0;
517
518 err = nla_parse(tb_msg, MACSEC_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
519 genlmsg_attrlen(gnlh, 0), main_policy);
520 if (err < 0)
521 return 0;
522
523 if (!tb_msg[MACSEC_ATTR_IFINDEX])
524 return 0;
525
526 if (nla_get_u32(tb_msg[MACSEC_ATTR_IFINDEX]) != (u32) arg->ifindex)
527 return 0;
528
529 if (arg->txsa < 4 && !tb_msg[MACSEC_ATTR_TXSA_LIST]) {
530 return 0;
531 } else if (arg->txsa < 4) {
532 struct nlattr *nla;
533 int rem;
534
535 nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_TXSA_LIST], rem) {
536 struct nlattr *tb[MACSEC_SA_ATTR_MAX + 1];
537
538 err = nla_parse_nested(tb, MACSEC_SA_ATTR_MAX, nla,
539 sa_policy);
540 if (err < 0)
541 continue;
542 if (!tb[MACSEC_SA_ATTR_AN])
543 continue;
544 if (nla_get_u8(tb[MACSEC_SA_ATTR_AN]) != arg->txsa)
545 continue;
546 if (!tb[MACSEC_SA_ATTR_PN])
547 return 0;
548 *arg->pn = nla_get_u32(tb[MACSEC_SA_ATTR_PN]);
549 return 0;
550 }
551
552 return 0;
553 }
554
555 if (arg->rxsci == UNUSED_SCI)
556 return 0;
557
558 if (tb_msg[MACSEC_ATTR_RXSC_LIST]) {
559 struct nlattr *nla;
560 int rem;
561
562 nla_for_each_nested(nla, tb_msg[MACSEC_ATTR_RXSC_LIST], rem) {
563 struct nlattr *tb[MACSEC_RXSC_ATTR_MAX + 1];
564
565 err = nla_parse_nested(tb, MACSEC_RXSC_ATTR_MAX, nla,
566 sc_policy);
567 if (err < 0)
568 return 0;
569 if (!tb[MACSEC_RXSC_ATTR_SCI])
570 continue;
571 if (nla_get_u64(tb[MACSEC_RXSC_ATTR_SCI]) != arg->rxsci)
572 continue;
573 if (!tb[MACSEC_RXSC_ATTR_SA_LIST])
574 return 0;
575
576 nla_for_each_nested(nla, tb[MACSEC_RXSC_ATTR_SA_LIST],
577 rem) {
578 struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
579
580 err = nla_parse_nested(tb_sa,
581 MACSEC_SA_ATTR_MAX, nla,
582 sa_policy);
583 if (err < 0)
584 continue;
585 if (!tb_sa[MACSEC_SA_ATTR_AN])
586 continue;
587 if (nla_get_u8(tb_sa[MACSEC_SA_ATTR_AN]) !=
588 arg->rxsa)
589 continue;
590 if (!tb_sa[MACSEC_SA_ATTR_PN])
591 return 0;
592 *arg->pn =
593 nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]);
594
595 return 0;
596 }
597
598 return 0;
599 }
600
601 return 0;
602 }
603
604 return 0;
605 }
606
607
nl_send_recv(struct nl_sock * sk,struct nl_msg * msg)608 static int nl_send_recv(struct nl_sock *sk, struct nl_msg *msg)
609 {
610 int ret;
611
612 ret = nl_send_auto_complete(sk, msg);
613 if (ret < 0) {
614 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to send: %d (%s)",
615 __func__, ret, nl_geterror(-ret));
616 return ret;
617 }
618
619 ret = nl_recvmsgs_default(sk);
620 if (ret < 0) {
621 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to recv: %d (%s)",
622 __func__, ret, nl_geterror(-ret));
623 }
624
625 return ret;
626 }
627
628
do_dump(struct macsec_drv_data * drv,u8 txsa,u64 rxsci,u8 rxsa,u32 * pn)629 static int do_dump(struct macsec_drv_data *drv, u8 txsa, u64 rxsci, u8 rxsa,
630 u32 *pn)
631 {
632 struct macsec_genl_ctx *ctx = &drv->ctx;
633 struct nl_msg *msg;
634 int ret = 1;
635
636 ctx->cb_arg.ifindex = drv->ifi;
637 ctx->cb_arg.rxsci = rxsci;
638 ctx->cb_arg.rxsa = rxsa;
639 ctx->cb_arg.txsa = txsa;
640 ctx->cb_arg.pn = pn;
641
642 msg = nlmsg_alloc();
643 if (!msg) {
644 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to alloc message",
645 __func__);
646 return 1;
647 }
648
649 if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, ctx->macsec_genl_id, 0,
650 NLM_F_DUMP, MACSEC_CMD_GET_TXSC, 0)) {
651 wpa_printf(MSG_ERROR, DRV_PREFIX "%s: failed to put header",
652 __func__);
653 goto out_free_msg;
654 }
655
656 ret = nl_send_recv(ctx->sk, msg);
657 if (ret < 0)
658 wpa_printf(MSG_ERROR,
659 DRV_PREFIX "failed to communicate: %d (%s)",
660 ret, nl_geterror(-ret));
661
662 ctx->cb_arg.pn = NULL;
663
664 out_free_msg:
665 nlmsg_free(msg);
666 return ret;
667 }
668
669
670 /**
671 * macsec_drv_get_receive_lowest_pn - Get receive lowest PN
672 * @priv: Private driver interface data
673 * @sa: secure association
674 * Returns: 0 on success, -1 on failure (or if not supported)
675 */
macsec_drv_get_receive_lowest_pn(void * priv,struct receive_sa * sa)676 static int macsec_drv_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
677 {
678 struct macsec_drv_data *drv = priv;
679 int err;
680
681 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s", __func__);
682
683 err = do_dump(drv, 0xff, mka_sci_u64(&sa->sc->sci), sa->an,
684 &sa->lowest_pn);
685 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: result %d", __func__,
686 sa->lowest_pn);
687
688 return err;
689 }
690
691
692 /**
693 * macsec_drv_set_receive_lowest_pn - Set receive lowest PN
694 * @priv: Private driver interface data
695 * @sa: secure association
696 * Returns: 0 on success, -1 on failure (or if not supported)
697 */
macsec_drv_set_receive_lowest_pn(void * priv,struct receive_sa * sa)698 static int macsec_drv_set_receive_lowest_pn(void *priv, struct receive_sa *sa)
699 {
700 struct macsec_drv_data *drv = priv;
701 struct macsec_genl_ctx *ctx = &drv->ctx;
702 struct nl_msg *msg;
703 struct nlattr *nest;
704 int ret = -1;
705
706 wpa_printf(MSG_DEBUG,
707 DRV_PREFIX "%s: set_receive_lowest_pn -> %d: %d",
708 drv->ifname, sa->an, sa->next_pn);
709
710 msg = msg_prepare(MACSEC_CMD_UPD_RXSA, ctx, drv->ifi);
711 if (!msg)
712 return ret;
713
714 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
715 if (!nest)
716 goto nla_put_failure;
717
718 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
719 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
720
721 nla_nest_end(msg, nest);
722
723 ret = nl_send_recv(ctx->sk, msg);
724 if (ret < 0) {
725 wpa_printf(MSG_ERROR,
726 DRV_PREFIX "failed to communicate: %d (%s)",
727 ret, nl_geterror(-ret));
728 }
729
730 nla_put_failure:
731 nlmsg_free(msg);
732 return ret;
733 }
734
735
736 /**
737 * macsec_drv_get_transmit_next_pn - Get transmit next PN
738 * @priv: Private driver interface data
739 * @sa: secure association
740 * Returns: 0 on success, -1 on failure (or if not supported)
741 */
macsec_drv_get_transmit_next_pn(void * priv,struct transmit_sa * sa)742 static int macsec_drv_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
743 {
744 struct macsec_drv_data *drv = priv;
745 int err;
746
747 wpa_printf(MSG_DEBUG, "%s", __func__);
748
749 err = do_dump(drv, sa->an, UNUSED_SCI, 0xff, &sa->next_pn);
750 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: err %d result %d", __func__, err,
751 sa->next_pn);
752 return err;
753 }
754
755
756 /**
757 * macsec_drv_set_transmit_next_pn - Set transmit next pn
758 * @priv: Private driver interface data
759 * @sa: secure association
760 * Returns: 0 on success, -1 on failure (or if not supported)
761 */
macsec_drv_set_transmit_next_pn(void * priv,struct transmit_sa * sa)762 static int macsec_drv_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
763 {
764 struct macsec_drv_data *drv = priv;
765 struct macsec_genl_ctx *ctx = &drv->ctx;
766 struct nl_msg *msg;
767 struct nlattr *nest;
768 int ret = -1;
769
770 wpa_printf(MSG_DEBUG, "%s -> %d: %d", __func__, sa->an, sa->next_pn);
771
772 msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, drv->ifi);
773 if (!msg)
774 return ret;
775
776 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
777 if (!nest)
778 goto nla_put_failure;
779
780 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
781 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
782
783 nla_nest_end(msg, nest);
784
785 ret = nl_send_recv(ctx->sk, msg);
786 if (ret < 0) {
787 wpa_printf(MSG_ERROR,
788 DRV_PREFIX "failed to communicate: %d (%s)",
789 ret, nl_geterror(-ret));
790 }
791
792 nla_put_failure:
793 nlmsg_free(msg);
794 return ret;
795 }
796
797
798 #define SCISTR MACSTR "::%hx"
799 #define SCI2STR(addr, port) MAC2STR(addr), htons(port)
800
801 /**
802 * macsec_drv_create_receive_sc - Create secure channel for receiving
803 * @priv: Private driver interface data
804 * @sc: secure channel
805 * @sci_addr: secure channel identifier - address
806 * @sci_port: secure channel identifier - port
807 * @conf_offset: confidentiality offset (0, 30, or 50)
808 * @validation: frame validation policy (0 = Disabled, 1 = Checked,
809 * 2 = Strict)
810 * Returns: 0 on success, -1 on failure (or if not supported)
811 */
macsec_drv_create_receive_sc(void * priv,struct receive_sc * sc,unsigned int conf_offset,int validation)812 static int macsec_drv_create_receive_sc(void *priv, struct receive_sc *sc,
813 unsigned int conf_offset,
814 int validation)
815 {
816 struct macsec_drv_data *drv = priv;
817 struct macsec_genl_ctx *ctx = &drv->ctx;
818 struct nl_msg *msg;
819 int ret = -1;
820
821 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: create_receive_sc -> " SCISTR
822 " (conf_offset=%u validation=%d)",
823 drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port),
824 conf_offset, validation);
825
826 msg = msg_prepare(MACSEC_CMD_ADD_RXSC, ctx, drv->ifi);
827 if (!msg)
828 return ret;
829
830 if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
831 goto nla_put_failure;
832
833 ret = nl_send_recv(ctx->sk, msg);
834 if (ret < 0) {
835 wpa_printf(MSG_ERROR,
836 DRV_PREFIX "%s: failed to communicate: %d (%s)",
837 __func__, ret, nl_geterror(-ret));
838 }
839
840 nla_put_failure:
841 nlmsg_free(msg);
842 return ret;
843 }
844
845
846 /**
847 * macsec_drv_delete_receive_sc - Delete secure connection for receiving
848 * @priv: private driver interface data from init()
849 * @sc: secure channel
850 * Returns: 0 on success, -1 on failure
851 */
macsec_drv_delete_receive_sc(void * priv,struct receive_sc * sc)852 static int macsec_drv_delete_receive_sc(void *priv, struct receive_sc *sc)
853 {
854 struct macsec_drv_data *drv = priv;
855 struct macsec_genl_ctx *ctx = &drv->ctx;
856 struct nl_msg *msg;
857 int ret = -1;
858
859 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_receive_sc -> " SCISTR,
860 drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port));
861
862 msg = msg_prepare(MACSEC_CMD_DEL_RXSC, ctx, drv->ifi);
863 if (!msg)
864 return ret;
865
866 if (nla_put_rxsc_config(msg, mka_sci_u64(&sc->sci)))
867 goto nla_put_failure;
868
869 ret = nl_send_recv(ctx->sk, msg);
870 if (ret < 0) {
871 wpa_printf(MSG_ERROR,
872 DRV_PREFIX "%s: failed to communicate: %d (%s)",
873 __func__, ret, nl_geterror(-ret));
874 }
875
876 nla_put_failure:
877 nlmsg_free(msg);
878 return ret;
879 }
880
881
882 /**
883 * macsec_drv_create_receive_sa - Create secure association for receive
884 * @priv: private driver interface data from init()
885 * @sa: secure association
886 * Returns: 0 on success, -1 on failure
887 */
macsec_drv_create_receive_sa(void * priv,struct receive_sa * sa)888 static int macsec_drv_create_receive_sa(void *priv, struct receive_sa *sa)
889 {
890 struct macsec_drv_data *drv = priv;
891 struct macsec_genl_ctx *ctx = &drv->ctx;
892 struct nl_msg *msg;
893 struct nlattr *nest;
894 int ret = -1;
895
896 wpa_printf(MSG_DEBUG,
897 DRV_PREFIX "%s: create_receive_sa -> %d on " SCISTR
898 " (enable_receive=%d next_pn=%u)",
899 drv->ifname, sa->an,
900 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port),
901 sa->enable_receive, sa->next_pn);
902 wpa_hexdump(MSG_DEBUG, DRV_PREFIX "SA keyid",
903 &sa->pkey->key_identifier,
904 sizeof(sa->pkey->key_identifier));
905 wpa_hexdump_key(MSG_DEBUG, DRV_PREFIX "SA key",
906 sa->pkey->key, sa->pkey->key_len);
907
908 msg = msg_prepare(MACSEC_CMD_ADD_RXSA, ctx, drv->ifi);
909 if (!msg)
910 return ret;
911
912 if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
913 goto nla_put_failure;
914
915 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
916 if (!nest)
917 goto nla_put_failure;
918
919 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
920 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_receive);
921 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
922 NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
923 &sa->pkey->key_identifier);
924 NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
925
926 nla_nest_end(msg, nest);
927
928 ret = nl_send_recv(ctx->sk, msg);
929 if (ret < 0) {
930 wpa_printf(MSG_ERROR,
931 DRV_PREFIX "%s: failed to communicate: %d (%s)",
932 __func__, ret, nl_geterror(-ret));
933 }
934
935 nla_put_failure:
936 nlmsg_free(msg);
937 return ret;
938 }
939
940
941 /**
942 * macsec_drv_delete_receive_sa - Delete secure association for receive
943 * @priv: private driver interface data from init()
944 * @sa: secure association
945 * Returns: 0 on success, -1 on failure
946 */
macsec_drv_delete_receive_sa(void * priv,struct receive_sa * sa)947 static int macsec_drv_delete_receive_sa(void *priv, struct receive_sa *sa)
948 {
949 struct macsec_drv_data *drv = priv;
950 struct macsec_genl_ctx *ctx = &drv->ctx;
951 struct nl_msg *msg;
952 struct nlattr *nest;
953 int ret = -1;
954
955 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_receive_sa -> %d on "
956 SCISTR, drv->ifname, sa->an,
957 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
958
959 msg = msg_prepare(MACSEC_CMD_DEL_RXSA, ctx, drv->ifi);
960 if (!msg)
961 return ret;
962
963 if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci)))
964 goto nla_put_failure;
965
966 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
967 if (!nest)
968 goto nla_put_failure;
969
970 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
971
972 nla_nest_end(msg, nest);
973
974 ret = nl_send_recv(ctx->sk, msg);
975 if (ret < 0) {
976 wpa_printf(MSG_ERROR,
977 DRV_PREFIX "%s: failed to communicate: %d (%s)",
978 __func__, ret, nl_geterror(-ret));
979 }
980
981 nla_put_failure:
982 nlmsg_free(msg);
983 return ret;
984 }
985
986
set_active_rx_sa(const struct macsec_genl_ctx * ctx,int ifindex,u64 sci,unsigned char an,Boolean state)987 static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
988 u64 sci, unsigned char an, Boolean state)
989 {
990 struct nl_msg *msg;
991 struct nlattr *nest;
992 int ret = -1;
993
994 msg = msg_prepare(MACSEC_CMD_UPD_RXSA, ctx, ifindex);
995 if (!msg)
996 return ret;
997
998 if (nla_put_rxsc_config(msg, sci))
999 goto nla_put_failure;
1000
1001 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1002 if (!nest)
1003 goto nla_put_failure;
1004
1005 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
1006 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
1007
1008 nla_nest_end(msg, nest);
1009
1010 ret = nl_send_recv(ctx->sk, msg);
1011 if (ret < 0)
1012 wpa_printf(MSG_ERROR,
1013 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1014 __func__, ret, nl_geterror(-ret));
1015
1016 nla_put_failure:
1017 nlmsg_free(msg);
1018 return ret;
1019 }
1020
1021
1022 /**
1023 * macsec_drv_enable_receive_sa - Enable the SA for receive
1024 * @priv: private driver interface data from init()
1025 * @sa: secure association
1026 * Returns: 0 on success, -1 on failure
1027 */
macsec_drv_enable_receive_sa(void * priv,struct receive_sa * sa)1028 static int macsec_drv_enable_receive_sa(void *priv, struct receive_sa *sa)
1029 {
1030 struct macsec_drv_data *drv = priv;
1031 struct macsec_genl_ctx *ctx = &drv->ctx;
1032
1033 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: enable_receive_sa -> %d on "
1034 SCISTR, drv->ifname, sa->an,
1035 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1036
1037 return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
1038 sa->an, TRUE);
1039 }
1040
1041
1042 /**
1043 * macsec_drv_disable_receive_sa - Disable SA for receive
1044 * @priv: private driver interface data from init()
1045 * @sa: secure association
1046 * Returns: 0 on success, -1 on failure
1047 */
macsec_drv_disable_receive_sa(void * priv,struct receive_sa * sa)1048 static int macsec_drv_disable_receive_sa(void *priv, struct receive_sa *sa)
1049 {
1050 struct macsec_drv_data *drv = priv;
1051 struct macsec_genl_ctx *ctx = &drv->ctx;
1052
1053 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: disable_receive_sa -> %d on "
1054 SCISTR, drv->ifname, sa->an,
1055 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1056
1057 return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci),
1058 sa->an, FALSE);
1059 }
1060
1061
lookup_sc(struct nl_cache * cache,int parent,u64 sci)1062 static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci)
1063 {
1064 struct rtnl_link *needle;
1065 void *match;
1066
1067 needle = rtnl_link_macsec_alloc();
1068 if (!needle)
1069 return NULL;
1070
1071 rtnl_link_set_link(needle, parent);
1072 rtnl_link_macsec_set_sci(needle, sci);
1073
1074 match = nl_cache_find(cache, (struct nl_object *) needle);
1075 rtnl_link_put(needle);
1076
1077 return (struct rtnl_link *) match;
1078 }
1079
1080
1081 /**
1082 * macsec_drv_create_transmit_sc - Create secure connection for transmit
1083 * @priv: private driver interface data from init()
1084 * @sc: secure channel
1085 * @conf_offset: confidentiality offset
1086 * Returns: 0 on success, -1 on failure
1087 */
macsec_drv_create_transmit_sc(void * priv,struct transmit_sc * sc,unsigned int conf_offset)1088 static int macsec_drv_create_transmit_sc(
1089 void *priv, struct transmit_sc *sc,
1090 unsigned int conf_offset)
1091 {
1092 struct macsec_drv_data *drv = priv;
1093 struct rtnl_link *link;
1094 char *ifname;
1095 u64 sci;
1096 int err;
1097
1098 wpa_printf(MSG_DEBUG, DRV_PREFIX
1099 "%s: create_transmit_sc -> " SCISTR " (conf_offset=%d)",
1100 drv->common.ifname, SCI2STR(sc->sci.addr, sc->sci.port),
1101 conf_offset);
1102
1103 if (!drv->sk) {
1104 wpa_printf(MSG_ERROR, DRV_PREFIX "NULL rtnl socket");
1105 return -1;
1106 }
1107
1108 link = rtnl_link_macsec_alloc();
1109 if (!link) {
1110 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
1111 return -1;
1112 }
1113
1114 rtnl_link_set_link(link, drv->parent_ifi);
1115
1116 sci = mka_sci_u64(&sc->sci);
1117 rtnl_link_macsec_set_sci(link, sci);
1118
1119 drv->created_link = TRUE;
1120
1121 err = rtnl_link_add(drv->sk, link, NLM_F_CREATE);
1122 if (err == -NLE_BUSY) {
1123 wpa_printf(MSG_INFO,
1124 DRV_PREFIX "link already exists, using it");
1125 drv->created_link = FALSE;
1126 } else if (err < 0) {
1127 rtnl_link_put(link);
1128 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d",
1129 err);
1130 return err;
1131 }
1132
1133 rtnl_link_put(link);
1134
1135 nl_cache_refill(drv->sk, drv->link_cache);
1136 link = lookup_sc(drv->link_cache, drv->parent_ifi, sci);
1137 if (!link) {
1138 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't find link");
1139 return -1;
1140 }
1141
1142 drv->ifi = rtnl_link_get_ifindex(link);
1143 ifname = rtnl_link_get_name(link);
1144 wpa_printf(MSG_DEBUG,
1145 DRV_PREFIX "%s: create_transmit_sc: ifi=%d ifname=%s",
1146 drv->common.ifname, drv->ifi, ifname);
1147 os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1148 rtnl_link_put(link);
1149
1150 drv->link = rtnl_link_macsec_alloc();
1151 if (!drv->link) {
1152 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't allocate link");
1153 return -1;
1154 }
1155
1156 rtnl_link_set_name(drv->link, drv->ifname);
1157
1158 /* In case some settings have already been done but we couldn't apply
1159 * them. */
1160 return try_commit(drv);
1161 }
1162
1163
1164 /**
1165 * macsec_drv_delete_transmit_sc - Delete secure connection for transmit
1166 * @priv: private driver interface data from init()
1167 * @sc: secure channel
1168 * Returns: 0 on success, -1 on failure
1169 */
macsec_drv_delete_transmit_sc(void * priv,struct transmit_sc * sc)1170 static int macsec_drv_delete_transmit_sc(void *priv, struct transmit_sc *sc)
1171 {
1172 struct macsec_drv_data *drv = priv;
1173 int err;
1174
1175 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_transmit_sc -> " SCISTR,
1176 drv->ifname, SCI2STR(sc->sci.addr, sc->sci.port));
1177
1178 if (!drv->sk)
1179 return 0;
1180
1181 if (!drv->created_link) {
1182 rtnl_link_put(drv->link);
1183 drv->link = NULL;
1184 wpa_printf(MSG_DEBUG, DRV_PREFIX
1185 "we didn't create the link, leave it alone");
1186 return 0;
1187 }
1188
1189 err = rtnl_link_delete(drv->sk, drv->link);
1190 if (err < 0)
1191 wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't delete link");
1192 rtnl_link_put(drv->link);
1193 drv->link = NULL;
1194
1195 return err;
1196 }
1197
1198
1199 /**
1200 * macsec_drv_create_transmit_sa - Create secure association for transmit
1201 * @priv: private driver interface data from init()
1202 * @sa: secure association
1203 * Returns: 0 on success, -1 on failure
1204 */
macsec_drv_create_transmit_sa(void * priv,struct transmit_sa * sa)1205 static int macsec_drv_create_transmit_sa(void *priv, struct transmit_sa *sa)
1206 {
1207 struct macsec_drv_data *drv = priv;
1208 struct macsec_genl_ctx *ctx = &drv->ctx;
1209 struct nl_msg *msg;
1210 struct nlattr *nest;
1211 int ret = -1;
1212
1213 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: create_transmit_sa -> %d on "
1214 SCISTR " (enable_transmit=%d next_pn=%u)",
1215 drv->ifname, sa->an,
1216 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port),
1217 sa->enable_transmit, sa->next_pn);
1218 wpa_hexdump(MSG_DEBUG, DRV_PREFIX "SA keyid",
1219 &sa->pkey->key_identifier,
1220 sizeof(sa->pkey->key_identifier));
1221 wpa_hexdump_key(MSG_DEBUG, DRV_PREFIX "SA key",
1222 sa->pkey->key, sa->pkey->key_len);
1223
1224 msg = msg_prepare(MACSEC_CMD_ADD_TXSA, ctx, drv->ifi);
1225 if (!msg)
1226 return ret;
1227
1228 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1229 if (!nest)
1230 goto nla_put_failure;
1231
1232 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1233 NLA_PUT_U32(msg, MACSEC_SA_ATTR_PN, sa->next_pn);
1234 NLA_PUT(msg, MACSEC_SA_ATTR_KEYID, sizeof(sa->pkey->key_identifier),
1235 &sa->pkey->key_identifier);
1236 NLA_PUT(msg, MACSEC_SA_ATTR_KEY, sa->pkey->key_len, sa->pkey->key);
1237 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, sa->enable_transmit);
1238
1239 nla_nest_end(msg, nest);
1240
1241 ret = nl_send_recv(ctx->sk, msg);
1242 if (ret < 0) {
1243 wpa_printf(MSG_ERROR,
1244 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1245 __func__, ret, nl_geterror(-ret));
1246 }
1247
1248 nla_put_failure:
1249 nlmsg_free(msg);
1250 return ret;
1251 }
1252
1253
1254 /**
1255 * macsec_drv_delete_transmit_sa - Delete secure association for transmit
1256 * @priv: private driver interface data from init()
1257 * @sa: secure association
1258 * Returns: 0 on success, -1 on failure
1259 */
macsec_drv_delete_transmit_sa(void * priv,struct transmit_sa * sa)1260 static int macsec_drv_delete_transmit_sa(void *priv, struct transmit_sa *sa)
1261 {
1262 struct macsec_drv_data *drv = priv;
1263 struct macsec_genl_ctx *ctx = &drv->ctx;
1264 struct nl_msg *msg;
1265 struct nlattr *nest;
1266 int ret = -1;
1267
1268 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: delete_transmit_sa -> %d on "
1269 SCISTR, drv->ifname, sa->an,
1270 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1271
1272 msg = msg_prepare(MACSEC_CMD_DEL_TXSA, ctx, drv->ifi);
1273 if (!msg)
1274 return ret;
1275
1276 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1277 if (!nest)
1278 goto nla_put_failure;
1279
1280 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, sa->an);
1281
1282 nla_nest_end(msg, nest);
1283
1284 ret = nl_send_recv(ctx->sk, msg);
1285 if (ret < 0) {
1286 wpa_printf(MSG_ERROR,
1287 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1288 __func__, ret, nl_geterror(-ret));
1289 }
1290
1291 nla_put_failure:
1292 nlmsg_free(msg);
1293 return ret;
1294 }
1295
1296
set_active_tx_sa(const struct macsec_genl_ctx * ctx,int ifindex,unsigned char an,Boolean state)1297 static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex,
1298 unsigned char an, Boolean state)
1299 {
1300 struct nl_msg *msg;
1301 struct nlattr *nest;
1302 int ret = -1;
1303
1304 msg = msg_prepare(MACSEC_CMD_UPD_TXSA, ctx, ifindex);
1305 if (!msg)
1306 return ret;
1307
1308 nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG);
1309 if (!nest)
1310 goto nla_put_failure;
1311
1312 NLA_PUT_U8(msg, MACSEC_SA_ATTR_AN, an);
1313 NLA_PUT_U8(msg, MACSEC_SA_ATTR_ACTIVE, !!state);
1314
1315 nla_nest_end(msg, nest);
1316
1317 ret = nl_send_recv(ctx->sk, msg);
1318 if (ret < 0) {
1319 wpa_printf(MSG_ERROR,
1320 DRV_PREFIX "%s: failed to communicate: %d (%s)",
1321 __func__, ret, nl_geterror(-ret));
1322 }
1323
1324 nla_put_failure:
1325 nlmsg_free(msg);
1326 return ret;
1327 }
1328
1329
1330 /**
1331 * macsec_drv_enable_transmit_sa - Enable SA for transmit
1332 * @priv: private driver interface data from init()
1333 * @sa: secure association
1334 * Returns: 0 on success, -1 on failure
1335 */
macsec_drv_enable_transmit_sa(void * priv,struct transmit_sa * sa)1336 static int macsec_drv_enable_transmit_sa(void *priv, struct transmit_sa *sa)
1337 {
1338 struct macsec_drv_data *drv = priv;
1339 struct macsec_genl_ctx *ctx = &drv->ctx;
1340 int ret;
1341
1342 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: enable_transmit_sa -> %d on "
1343 SCISTR, drv->ifname, sa->an,
1344 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1345
1346 ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE);
1347 if (ret < 0) {
1348 wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa");
1349 return ret;
1350 }
1351
1352 drv->encoding_sa_set = TRUE;
1353 drv->encoding_sa = sa->an;
1354
1355 return try_commit(drv);
1356 }
1357
1358
1359 /**
1360 * macsec_drv_disable_transmit_sa - Disable SA for transmit
1361 * @priv: private driver interface data from init()
1362 * @sa: secure association
1363 * Returns: 0 on success, -1 on failure
1364 */
macsec_drv_disable_transmit_sa(void * priv,struct transmit_sa * sa)1365 static int macsec_drv_disable_transmit_sa(void *priv, struct transmit_sa *sa)
1366 {
1367 struct macsec_drv_data *drv = priv;
1368 struct macsec_genl_ctx *ctx = &drv->ctx;
1369
1370 wpa_printf(MSG_DEBUG, DRV_PREFIX "%s: disable_transmit_sa -> %d on "
1371 SCISTR, drv->ifname, sa->an,
1372 SCI2STR(sa->sc->sci.addr, sa->sc->sci.port));
1373
1374 return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE);
1375 }
1376
1377
macsec_drv_status(void * priv,char * buf,size_t buflen)1378 static int macsec_drv_status(void *priv, char *buf, size_t buflen)
1379 {
1380 struct macsec_drv_data *drv = priv;
1381 int res;
1382 char *pos, *end;
1383
1384 pos = buf;
1385 end = buf + buflen;
1386
1387 res = os_snprintf(pos, end - pos,
1388 "ifname=%s\n"
1389 "ifi=%d\n"
1390 "parent_ifname=%s\n"
1391 "parent_ifi=%d\n",
1392 drv->common.ifname, drv->ifi,
1393 drv->ifname, drv->parent_ifi);
1394 if (os_snprintf_error(end - pos, res))
1395 return pos - buf;
1396 pos += res;
1397
1398 return pos - buf;
1399 }
1400
1401
1402 const struct wpa_driver_ops wpa_driver_macsec_linux_ops = {
1403 .name = "macsec_linux",
1404 .desc = "MACsec Ethernet driver for Linux",
1405 .get_ssid = driver_wired_get_ssid,
1406 .get_bssid = driver_wired_get_bssid,
1407 .get_capa = driver_wired_get_capa,
1408 .init = macsec_drv_wpa_init,
1409 .deinit = macsec_drv_wpa_deinit,
1410
1411 .macsec_init = macsec_drv_macsec_init,
1412 .macsec_deinit = macsec_drv_macsec_deinit,
1413 .macsec_get_capability = macsec_drv_get_capability,
1414 .enable_protect_frames = macsec_drv_enable_protect_frames,
1415 .enable_encrypt = macsec_drv_enable_encrypt,
1416 .set_replay_protect = macsec_drv_set_replay_protect,
1417 .set_current_cipher_suite = macsec_drv_set_current_cipher_suite,
1418 .enable_controlled_port = macsec_drv_enable_controlled_port,
1419 .get_receive_lowest_pn = macsec_drv_get_receive_lowest_pn,
1420 .set_receive_lowest_pn = macsec_drv_set_receive_lowest_pn,
1421 .get_transmit_next_pn = macsec_drv_get_transmit_next_pn,
1422 .set_transmit_next_pn = macsec_drv_set_transmit_next_pn,
1423 .create_receive_sc = macsec_drv_create_receive_sc,
1424 .delete_receive_sc = macsec_drv_delete_receive_sc,
1425 .create_receive_sa = macsec_drv_create_receive_sa,
1426 .delete_receive_sa = macsec_drv_delete_receive_sa,
1427 .enable_receive_sa = macsec_drv_enable_receive_sa,
1428 .disable_receive_sa = macsec_drv_disable_receive_sa,
1429 .create_transmit_sc = macsec_drv_create_transmit_sc,
1430 .delete_transmit_sc = macsec_drv_delete_transmit_sc,
1431 .create_transmit_sa = macsec_drv_create_transmit_sa,
1432 .delete_transmit_sa = macsec_drv_delete_transmit_sa,
1433 .enable_transmit_sa = macsec_drv_enable_transmit_sa,
1434 .disable_transmit_sa = macsec_drv_disable_transmit_sa,
1435
1436 .status = macsec_drv_status,
1437 };
1438