1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * ipmacsec.c "ip macsec".
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Sabrina Dubroca <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <linux/genetlink.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_ether.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_macsec.h>
19*de1e4e89SAndroid Build Coastguard Worker
20*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
21*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
22*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
23*de1e4e89SAndroid Build Coastguard Worker #include "ll_map.h"
24*de1e4e89SAndroid Build Coastguard Worker #include "libgenl.h"
25*de1e4e89SAndroid Build Coastguard Worker
26*de1e4e89SAndroid Build Coastguard Worker static const char *values_on_off[] = { "off", "on" };
27*de1e4e89SAndroid Build Coastguard Worker
28*de1e4e89SAndroid Build Coastguard Worker static const char *VALIDATE_STR[] = {
29*de1e4e89SAndroid Build Coastguard Worker [MACSEC_VALIDATE_DISABLED] = "disabled",
30*de1e4e89SAndroid Build Coastguard Worker [MACSEC_VALIDATE_CHECK] = "check",
31*de1e4e89SAndroid Build Coastguard Worker [MACSEC_VALIDATE_STRICT] = "strict",
32*de1e4e89SAndroid Build Coastguard Worker };
33*de1e4e89SAndroid Build Coastguard Worker
34*de1e4e89SAndroid Build Coastguard Worker struct sci {
35*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
36*de1e4e89SAndroid Build Coastguard Worker __u16 port;
37*de1e4e89SAndroid Build Coastguard Worker char abuf[6];
38*de1e4e89SAndroid Build Coastguard Worker };
39*de1e4e89SAndroid Build Coastguard Worker
40*de1e4e89SAndroid Build Coastguard Worker struct sa_desc {
41*de1e4e89SAndroid Build Coastguard Worker __u8 an;
42*de1e4e89SAndroid Build Coastguard Worker __u32 pn;
43*de1e4e89SAndroid Build Coastguard Worker __u8 key_id[MACSEC_KEYID_LEN];
44*de1e4e89SAndroid Build Coastguard Worker __u32 key_len;
45*de1e4e89SAndroid Build Coastguard Worker __u8 key[MACSEC_MAX_KEY_LEN];
46*de1e4e89SAndroid Build Coastguard Worker __u8 active;
47*de1e4e89SAndroid Build Coastguard Worker };
48*de1e4e89SAndroid Build Coastguard Worker
49*de1e4e89SAndroid Build Coastguard Worker struct cipher_args {
50*de1e4e89SAndroid Build Coastguard Worker __u64 id;
51*de1e4e89SAndroid Build Coastguard Worker __u8 icv_len;
52*de1e4e89SAndroid Build Coastguard Worker };
53*de1e4e89SAndroid Build Coastguard Worker
54*de1e4e89SAndroid Build Coastguard Worker struct txsc_desc {
55*de1e4e89SAndroid Build Coastguard Worker int ifindex;
56*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
57*de1e4e89SAndroid Build Coastguard Worker __be16 port;
58*de1e4e89SAndroid Build Coastguard Worker struct cipher_args cipher;
59*de1e4e89SAndroid Build Coastguard Worker __u32 window;
60*de1e4e89SAndroid Build Coastguard Worker enum macsec_validation_type validate;
61*de1e4e89SAndroid Build Coastguard Worker __u8 encoding_sa;
62*de1e4e89SAndroid Build Coastguard Worker };
63*de1e4e89SAndroid Build Coastguard Worker
64*de1e4e89SAndroid Build Coastguard Worker struct rxsc_desc {
65*de1e4e89SAndroid Build Coastguard Worker int ifindex;
66*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
67*de1e4e89SAndroid Build Coastguard Worker __u8 active;
68*de1e4e89SAndroid Build Coastguard Worker };
69*de1e4e89SAndroid Build Coastguard Worker
70*de1e4e89SAndroid Build Coastguard Worker #define MACSEC_BUFLEN 1024
71*de1e4e89SAndroid Build Coastguard Worker
72*de1e4e89SAndroid Build Coastguard Worker
73*de1e4e89SAndroid Build Coastguard Worker /* netlink socket */
74*de1e4e89SAndroid Build Coastguard Worker static struct rtnl_handle genl_rth;
75*de1e4e89SAndroid Build Coastguard Worker static int genl_family = -1;
76*de1e4e89SAndroid Build Coastguard Worker
77*de1e4e89SAndroid Build Coastguard Worker #define MACSEC_GENL_REQ(_req, _bufsiz, _cmd, _flags) \
78*de1e4e89SAndroid Build Coastguard Worker GENL_REQUEST(_req, _bufsiz, genl_family, 0, MACSEC_GENL_VERSION, \
79*de1e4e89SAndroid Build Coastguard Worker _cmd, _flags)
80*de1e4e89SAndroid Build Coastguard Worker
81*de1e4e89SAndroid Build Coastguard Worker
ipmacsec_usage(void)82*de1e4e89SAndroid Build Coastguard Worker static void ipmacsec_usage(void)
83*de1e4e89SAndroid Build Coastguard Worker {
84*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ip macsec add DEV tx sa { 0..3 } [ OPTS ] key ID KEY\n");
85*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec set DEV tx sa { 0..3 } [ OPTS ]\n");
86*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec del DEV tx sa { 0..3 }\n");
87*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec add DEV rx SCI [ on | off ]\n");
88*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec set DEV rx SCI [ on | off ]\n");
89*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec del DEV rx SCI\n");
90*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec add DEV rx SCI sa { 0..3 } [ OPTS ] key ID KEY\n");
91*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec set DEV rx SCI sa { 0..3 } [ OPTS ]\n");
92*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec del DEV rx SCI sa { 0..3 }\n");
93*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec show\n");
94*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ip macsec show DEV\n");
95*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "where OPTS := [ pn <u32> ] [ on | off ]\n");
96*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ID := 128-bit hex string\n");
97*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " KEY := 128-bit hex string\n");
98*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " SCI := { sci <u64> | port { 1..2^16-1 } address <lladdr> }\n");
99*de1e4e89SAndroid Build Coastguard Worker
100*de1e4e89SAndroid Build Coastguard Worker exit(-1);
101*de1e4e89SAndroid Build Coastguard Worker }
102*de1e4e89SAndroid Build Coastguard Worker
one_of(const char * msg,const char * realval,const char ** list,size_t len,int * index)103*de1e4e89SAndroid Build Coastguard Worker static int one_of(const char *msg, const char *realval, const char **list,
104*de1e4e89SAndroid Build Coastguard Worker size_t len, int *index)
105*de1e4e89SAndroid Build Coastguard Worker {
106*de1e4e89SAndroid Build Coastguard Worker int i;
107*de1e4e89SAndroid Build Coastguard Worker
108*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
109*de1e4e89SAndroid Build Coastguard Worker if (matches(realval, list[i]) == 0) {
110*de1e4e89SAndroid Build Coastguard Worker *index = i;
111*de1e4e89SAndroid Build Coastguard Worker return 0;
112*de1e4e89SAndroid Build Coastguard Worker }
113*de1e4e89SAndroid Build Coastguard Worker }
114*de1e4e89SAndroid Build Coastguard Worker
115*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Error: argument of \"%s\" must be one of ", msg);
116*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
117*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\"%s\", ", list[i]);
118*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "not \"%s\"\n", realval);
119*de1e4e89SAndroid Build Coastguard Worker return -1;
120*de1e4e89SAndroid Build Coastguard Worker }
121*de1e4e89SAndroid Build Coastguard Worker
get_an(__u8 * val,const char * arg)122*de1e4e89SAndroid Build Coastguard Worker static int get_an(__u8 *val, const char *arg)
123*de1e4e89SAndroid Build Coastguard Worker {
124*de1e4e89SAndroid Build Coastguard Worker int ret = get_u8(val, arg, 0);
125*de1e4e89SAndroid Build Coastguard Worker
126*de1e4e89SAndroid Build Coastguard Worker if (ret)
127*de1e4e89SAndroid Build Coastguard Worker return ret;
128*de1e4e89SAndroid Build Coastguard Worker
129*de1e4e89SAndroid Build Coastguard Worker if (*val > 3)
130*de1e4e89SAndroid Build Coastguard Worker return -1;
131*de1e4e89SAndroid Build Coastguard Worker
132*de1e4e89SAndroid Build Coastguard Worker return 0;
133*de1e4e89SAndroid Build Coastguard Worker }
134*de1e4e89SAndroid Build Coastguard Worker
get_sci(__u64 * sci,const char * arg)135*de1e4e89SAndroid Build Coastguard Worker static int get_sci(__u64 *sci, const char *arg)
136*de1e4e89SAndroid Build Coastguard Worker {
137*de1e4e89SAndroid Build Coastguard Worker return get_be64(sci, arg, 16);
138*de1e4e89SAndroid Build Coastguard Worker }
139*de1e4e89SAndroid Build Coastguard Worker
get_port(__be16 * port,const char * arg)140*de1e4e89SAndroid Build Coastguard Worker static int get_port(__be16 *port, const char *arg)
141*de1e4e89SAndroid Build Coastguard Worker {
142*de1e4e89SAndroid Build Coastguard Worker return get_be16(port, arg, 0);
143*de1e4e89SAndroid Build Coastguard Worker }
144*de1e4e89SAndroid Build Coastguard Worker
145*de1e4e89SAndroid Build Coastguard Worker #define _STR(a) #a
146*de1e4e89SAndroid Build Coastguard Worker #define STR(a) _STR(a)
147*de1e4e89SAndroid Build Coastguard Worker
get_icvlen(__u8 * icvlen,char * arg)148*de1e4e89SAndroid Build Coastguard Worker static void get_icvlen(__u8 *icvlen, char *arg)
149*de1e4e89SAndroid Build Coastguard Worker {
150*de1e4e89SAndroid Build Coastguard Worker int ret = get_u8(icvlen, arg, 10);
151*de1e4e89SAndroid Build Coastguard Worker
152*de1e4e89SAndroid Build Coastguard Worker if (ret)
153*de1e4e89SAndroid Build Coastguard Worker invarg("expected ICV length", arg);
154*de1e4e89SAndroid Build Coastguard Worker
155*de1e4e89SAndroid Build Coastguard Worker if (*icvlen < MACSEC_MIN_ICV_LEN || *icvlen > MACSEC_STD_ICV_LEN)
156*de1e4e89SAndroid Build Coastguard Worker invarg("ICV length must be in the range {"
157*de1e4e89SAndroid Build Coastguard Worker STR(MACSEC_MIN_ICV_LEN) ".." STR(MACSEC_STD_ICV_LEN)
158*de1e4e89SAndroid Build Coastguard Worker "}", arg);
159*de1e4e89SAndroid Build Coastguard Worker }
160*de1e4e89SAndroid Build Coastguard Worker
get_sa(int * argcp,char *** argvp,__u8 * an)161*de1e4e89SAndroid Build Coastguard Worker static bool get_sa(int *argcp, char ***argvp, __u8 *an)
162*de1e4e89SAndroid Build Coastguard Worker {
163*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
164*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
165*de1e4e89SAndroid Build Coastguard Worker int ret;
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0 || strcmp(*argv, "sa") != 0)
168*de1e4e89SAndroid Build Coastguard Worker return false;
169*de1e4e89SAndroid Build Coastguard Worker
170*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
171*de1e4e89SAndroid Build Coastguard Worker ret = get_an(an, *argv);
172*de1e4e89SAndroid Build Coastguard Worker if (ret)
173*de1e4e89SAndroid Build Coastguard Worker invarg("expected an { 0..3 }", *argv);
174*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
175*de1e4e89SAndroid Build Coastguard Worker
176*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
177*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
178*de1e4e89SAndroid Build Coastguard Worker return true;
179*de1e4e89SAndroid Build Coastguard Worker }
180*de1e4e89SAndroid Build Coastguard Worker
parse_sa_args(int * argcp,char *** argvp,struct sa_desc * sa)181*de1e4e89SAndroid Build Coastguard Worker static int parse_sa_args(int *argcp, char ***argvp, struct sa_desc *sa)
182*de1e4e89SAndroid Build Coastguard Worker {
183*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
184*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
185*de1e4e89SAndroid Build Coastguard Worker int ret;
186*de1e4e89SAndroid Build Coastguard Worker bool active_set = false;
187*de1e4e89SAndroid Build Coastguard Worker
188*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
189*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "pn") == 0) {
190*de1e4e89SAndroid Build Coastguard Worker if (sa->pn != 0)
191*de1e4e89SAndroid Build Coastguard Worker duparg2("pn", "pn");
192*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
193*de1e4e89SAndroid Build Coastguard Worker ret = get_u32(&sa->pn, *argv, 0);
194*de1e4e89SAndroid Build Coastguard Worker if (ret)
195*de1e4e89SAndroid Build Coastguard Worker invarg("expected pn", *argv);
196*de1e4e89SAndroid Build Coastguard Worker if (sa->pn == 0)
197*de1e4e89SAndroid Build Coastguard Worker invarg("expected pn != 0", *argv);
198*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "key") == 0) {
199*de1e4e89SAndroid Build Coastguard Worker unsigned int len;
200*de1e4e89SAndroid Build Coastguard Worker
201*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
202*de1e4e89SAndroid Build Coastguard Worker if (!hexstring_a2n(*argv, sa->key_id, MACSEC_KEYID_LEN,
203*de1e4e89SAndroid Build Coastguard Worker &len))
204*de1e4e89SAndroid Build Coastguard Worker invarg("expected key id", *argv);
205*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
206*de1e4e89SAndroid Build Coastguard Worker if (!hexstring_a2n(*argv, sa->key, MACSEC_MAX_KEY_LEN,
207*de1e4e89SAndroid Build Coastguard Worker &sa->key_len))
208*de1e4e89SAndroid Build Coastguard Worker invarg("expected key", *argv);
209*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "on") == 0) {
210*de1e4e89SAndroid Build Coastguard Worker if (active_set)
211*de1e4e89SAndroid Build Coastguard Worker duparg2("on/off", "on");
212*de1e4e89SAndroid Build Coastguard Worker sa->active = true;
213*de1e4e89SAndroid Build Coastguard Worker active_set = true;
214*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "off") == 0) {
215*de1e4e89SAndroid Build Coastguard Worker if (active_set)
216*de1e4e89SAndroid Build Coastguard Worker duparg2("on/off", "off");
217*de1e4e89SAndroid Build Coastguard Worker sa->active = false;
218*de1e4e89SAndroid Build Coastguard Worker active_set = true;
219*de1e4e89SAndroid Build Coastguard Worker } else {
220*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "macsec: unknown command \"%s\"?\n",
221*de1e4e89SAndroid Build Coastguard Worker *argv);
222*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
223*de1e4e89SAndroid Build Coastguard Worker }
224*de1e4e89SAndroid Build Coastguard Worker
225*de1e4e89SAndroid Build Coastguard Worker argv++; argc--;
226*de1e4e89SAndroid Build Coastguard Worker }
227*de1e4e89SAndroid Build Coastguard Worker
228*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
229*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
230*de1e4e89SAndroid Build Coastguard Worker return 0;
231*de1e4e89SAndroid Build Coastguard Worker }
232*de1e4e89SAndroid Build Coastguard Worker
make_sci(char * addr,__be16 port)233*de1e4e89SAndroid Build Coastguard Worker static __u64 make_sci(char *addr, __be16 port)
234*de1e4e89SAndroid Build Coastguard Worker {
235*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
236*de1e4e89SAndroid Build Coastguard Worker
237*de1e4e89SAndroid Build Coastguard Worker memcpy(&sci, addr, ETH_ALEN);
238*de1e4e89SAndroid Build Coastguard Worker memcpy(((char *)&sci) + ETH_ALEN, &port, sizeof(port));
239*de1e4e89SAndroid Build Coastguard Worker
240*de1e4e89SAndroid Build Coastguard Worker return sci;
241*de1e4e89SAndroid Build Coastguard Worker }
242*de1e4e89SAndroid Build Coastguard Worker
sci_complete(bool sci,bool port,bool addr,bool port_only)243*de1e4e89SAndroid Build Coastguard Worker static bool sci_complete(bool sci, bool port, bool addr, bool port_only)
244*de1e4e89SAndroid Build Coastguard Worker {
245*de1e4e89SAndroid Build Coastguard Worker return sci || (port && (addr || port_only));
246*de1e4e89SAndroid Build Coastguard Worker }
247*de1e4e89SAndroid Build Coastguard Worker
get_sci_portaddr(struct sci * sci,int * argcp,char *** argvp,bool port_only,bool optional)248*de1e4e89SAndroid Build Coastguard Worker static int get_sci_portaddr(struct sci *sci, int *argcp, char ***argvp,
249*de1e4e89SAndroid Build Coastguard Worker bool port_only, bool optional)
250*de1e4e89SAndroid Build Coastguard Worker {
251*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
252*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
253*de1e4e89SAndroid Build Coastguard Worker int ret;
254*de1e4e89SAndroid Build Coastguard Worker bool p = false, a = false, s = false;
255*de1e4e89SAndroid Build Coastguard Worker
256*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
257*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "sci") == 0) {
258*de1e4e89SAndroid Build Coastguard Worker if (p)
259*de1e4e89SAndroid Build Coastguard Worker invarg("expected address", *argv);
260*de1e4e89SAndroid Build Coastguard Worker if (a)
261*de1e4e89SAndroid Build Coastguard Worker invarg("expected port", *argv);
262*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
263*de1e4e89SAndroid Build Coastguard Worker ret = get_sci(&sci->sci, *argv);
264*de1e4e89SAndroid Build Coastguard Worker if (ret)
265*de1e4e89SAndroid Build Coastguard Worker invarg("expected sci", *argv);
266*de1e4e89SAndroid Build Coastguard Worker s = true;
267*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "port") == 0) {
268*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
269*de1e4e89SAndroid Build Coastguard Worker ret = get_port(&sci->port, *argv);
270*de1e4e89SAndroid Build Coastguard Worker if (ret)
271*de1e4e89SAndroid Build Coastguard Worker invarg("expected port", *argv);
272*de1e4e89SAndroid Build Coastguard Worker if (sci->port == 0)
273*de1e4e89SAndroid Build Coastguard Worker invarg("expected port != 0", *argv);
274*de1e4e89SAndroid Build Coastguard Worker p = true;
275*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "address") == 0) {
276*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
277*de1e4e89SAndroid Build Coastguard Worker ret = ll_addr_a2n(sci->abuf, sizeof(sci->abuf), *argv);
278*de1e4e89SAndroid Build Coastguard Worker if (ret < 0)
279*de1e4e89SAndroid Build Coastguard Worker invarg("expected lladdr", *argv);
280*de1e4e89SAndroid Build Coastguard Worker a = true;
281*de1e4e89SAndroid Build Coastguard Worker } else if (optional) {
282*de1e4e89SAndroid Build Coastguard Worker break;
283*de1e4e89SAndroid Build Coastguard Worker } else {
284*de1e4e89SAndroid Build Coastguard Worker invarg("expected sci, port, or address", *argv);
285*de1e4e89SAndroid Build Coastguard Worker }
286*de1e4e89SAndroid Build Coastguard Worker
287*de1e4e89SAndroid Build Coastguard Worker argv++; argc--;
288*de1e4e89SAndroid Build Coastguard Worker
289*de1e4e89SAndroid Build Coastguard Worker if (sci_complete(s, p, a, port_only))
290*de1e4e89SAndroid Build Coastguard Worker break;
291*de1e4e89SAndroid Build Coastguard Worker }
292*de1e4e89SAndroid Build Coastguard Worker
293*de1e4e89SAndroid Build Coastguard Worker if (!optional && !sci_complete(s, p, a, port_only))
294*de1e4e89SAndroid Build Coastguard Worker return -1;
295*de1e4e89SAndroid Build Coastguard Worker
296*de1e4e89SAndroid Build Coastguard Worker if (p && a)
297*de1e4e89SAndroid Build Coastguard Worker sci->sci = make_sci(sci->abuf, sci->port);
298*de1e4e89SAndroid Build Coastguard Worker
299*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
300*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
301*de1e4e89SAndroid Build Coastguard Worker
302*de1e4e89SAndroid Build Coastguard Worker return p || a || s;
303*de1e4e89SAndroid Build Coastguard Worker }
304*de1e4e89SAndroid Build Coastguard Worker
parse_rxsci(int * argcp,char *** argvp,struct rxsc_desc * rxsc,struct sa_desc * rxsa)305*de1e4e89SAndroid Build Coastguard Worker static bool parse_rxsci(int *argcp, char ***argvp, struct rxsc_desc *rxsc,
306*de1e4e89SAndroid Build Coastguard Worker struct sa_desc *rxsa)
307*de1e4e89SAndroid Build Coastguard Worker {
308*de1e4e89SAndroid Build Coastguard Worker struct sci sci = { 0 };
309*de1e4e89SAndroid Build Coastguard Worker
310*de1e4e89SAndroid Build Coastguard Worker if (*argcp == 0 ||
311*de1e4e89SAndroid Build Coastguard Worker get_sci_portaddr(&sci, argcp, argvp, false, false) < 0) {
312*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "expected sci\n");
313*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
314*de1e4e89SAndroid Build Coastguard Worker }
315*de1e4e89SAndroid Build Coastguard Worker
316*de1e4e89SAndroid Build Coastguard Worker rxsc->sci = sci.sci;
317*de1e4e89SAndroid Build Coastguard Worker
318*de1e4e89SAndroid Build Coastguard Worker return get_sa(argcp, argvp, &rxsa->an);
319*de1e4e89SAndroid Build Coastguard Worker }
320*de1e4e89SAndroid Build Coastguard Worker
parse_rxsci_args(int * argcp,char *** argvp,struct rxsc_desc * rxsc)321*de1e4e89SAndroid Build Coastguard Worker static int parse_rxsci_args(int *argcp, char ***argvp, struct rxsc_desc *rxsc)
322*de1e4e89SAndroid Build Coastguard Worker {
323*de1e4e89SAndroid Build Coastguard Worker int argc = *argcp;
324*de1e4e89SAndroid Build Coastguard Worker char **argv = *argvp;
325*de1e4e89SAndroid Build Coastguard Worker bool active_set = false;
326*de1e4e89SAndroid Build Coastguard Worker
327*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
328*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "on") == 0) {
329*de1e4e89SAndroid Build Coastguard Worker if (active_set)
330*de1e4e89SAndroid Build Coastguard Worker duparg2("on/off", "on");
331*de1e4e89SAndroid Build Coastguard Worker rxsc->active = true;
332*de1e4e89SAndroid Build Coastguard Worker active_set = true;
333*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "off") == 0) {
334*de1e4e89SAndroid Build Coastguard Worker if (active_set)
335*de1e4e89SAndroid Build Coastguard Worker duparg2("on/off", "off");
336*de1e4e89SAndroid Build Coastguard Worker rxsc->active = false;
337*de1e4e89SAndroid Build Coastguard Worker active_set = true;
338*de1e4e89SAndroid Build Coastguard Worker } else {
339*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "macsec: unknown command \"%s\"?\n",
340*de1e4e89SAndroid Build Coastguard Worker *argv);
341*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
342*de1e4e89SAndroid Build Coastguard Worker }
343*de1e4e89SAndroid Build Coastguard Worker
344*de1e4e89SAndroid Build Coastguard Worker argv++; argc--;
345*de1e4e89SAndroid Build Coastguard Worker }
346*de1e4e89SAndroid Build Coastguard Worker
347*de1e4e89SAndroid Build Coastguard Worker *argvp = argv;
348*de1e4e89SAndroid Build Coastguard Worker *argcp = argc;
349*de1e4e89SAndroid Build Coastguard Worker return 0;
350*de1e4e89SAndroid Build Coastguard Worker }
351*de1e4e89SAndroid Build Coastguard Worker
352*de1e4e89SAndroid Build Coastguard Worker enum cmd {
353*de1e4e89SAndroid Build Coastguard Worker CMD_ADD,
354*de1e4e89SAndroid Build Coastguard Worker CMD_DEL,
355*de1e4e89SAndroid Build Coastguard Worker CMD_UPD,
356*de1e4e89SAndroid Build Coastguard Worker __CMD_MAX
357*de1e4e89SAndroid Build Coastguard Worker };
358*de1e4e89SAndroid Build Coastguard Worker
359*de1e4e89SAndroid Build Coastguard Worker static const enum macsec_nl_commands macsec_commands[__CMD_MAX][2][2] = {
360*de1e4e89SAndroid Build Coastguard Worker [CMD_ADD] = {
361*de1e4e89SAndroid Build Coastguard Worker [0] = {-1, MACSEC_CMD_ADD_RXSC},
362*de1e4e89SAndroid Build Coastguard Worker [1] = {MACSEC_CMD_ADD_TXSA, MACSEC_CMD_ADD_RXSA},
363*de1e4e89SAndroid Build Coastguard Worker },
364*de1e4e89SAndroid Build Coastguard Worker [CMD_UPD] = {
365*de1e4e89SAndroid Build Coastguard Worker [0] = {-1, MACSEC_CMD_UPD_RXSC},
366*de1e4e89SAndroid Build Coastguard Worker [1] = {MACSEC_CMD_UPD_TXSA, MACSEC_CMD_UPD_RXSA},
367*de1e4e89SAndroid Build Coastguard Worker },
368*de1e4e89SAndroid Build Coastguard Worker [CMD_DEL] = {
369*de1e4e89SAndroid Build Coastguard Worker [0] = {-1, MACSEC_CMD_DEL_RXSC},
370*de1e4e89SAndroid Build Coastguard Worker [1] = {MACSEC_CMD_DEL_TXSA, MACSEC_CMD_DEL_RXSA},
371*de1e4e89SAndroid Build Coastguard Worker },
372*de1e4e89SAndroid Build Coastguard Worker };
373*de1e4e89SAndroid Build Coastguard Worker
do_modify_nl(enum cmd c,enum macsec_nl_commands cmd,int ifindex,struct rxsc_desc * rxsc,struct sa_desc * sa)374*de1e4e89SAndroid Build Coastguard Worker static int do_modify_nl(enum cmd c, enum macsec_nl_commands cmd, int ifindex,
375*de1e4e89SAndroid Build Coastguard Worker struct rxsc_desc *rxsc, struct sa_desc *sa)
376*de1e4e89SAndroid Build Coastguard Worker {
377*de1e4e89SAndroid Build Coastguard Worker struct rtattr *attr_sa;
378*de1e4e89SAndroid Build Coastguard Worker
379*de1e4e89SAndroid Build Coastguard Worker MACSEC_GENL_REQ(req, MACSEC_BUFLEN, cmd, NLM_F_REQUEST);
380*de1e4e89SAndroid Build Coastguard Worker
381*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_IFINDEX, ifindex);
382*de1e4e89SAndroid Build Coastguard Worker if (rxsc) {
383*de1e4e89SAndroid Build Coastguard Worker struct rtattr *attr_rxsc;
384*de1e4e89SAndroid Build Coastguard Worker
385*de1e4e89SAndroid Build Coastguard Worker attr_rxsc = addattr_nest(&req.n, MACSEC_BUFLEN,
386*de1e4e89SAndroid Build Coastguard Worker MACSEC_ATTR_RXSC_CONFIG);
387*de1e4e89SAndroid Build Coastguard Worker addattr64(&req.n, MACSEC_BUFLEN,
388*de1e4e89SAndroid Build Coastguard Worker MACSEC_RXSC_ATTR_SCI, rxsc->sci);
389*de1e4e89SAndroid Build Coastguard Worker if (c != CMD_DEL && rxsc->active != 0xff)
390*de1e4e89SAndroid Build Coastguard Worker addattr8(&req.n, MACSEC_BUFLEN,
391*de1e4e89SAndroid Build Coastguard Worker MACSEC_RXSC_ATTR_ACTIVE, rxsc->active);
392*de1e4e89SAndroid Build Coastguard Worker
393*de1e4e89SAndroid Build Coastguard Worker addattr_nest_end(&req.n, attr_rxsc);
394*de1e4e89SAndroid Build Coastguard Worker }
395*de1e4e89SAndroid Build Coastguard Worker
396*de1e4e89SAndroid Build Coastguard Worker if (sa->an == 0xff)
397*de1e4e89SAndroid Build Coastguard Worker goto talk;
398*de1e4e89SAndroid Build Coastguard Worker
399*de1e4e89SAndroid Build Coastguard Worker attr_sa = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_SA_CONFIG);
400*de1e4e89SAndroid Build Coastguard Worker
401*de1e4e89SAndroid Build Coastguard Worker addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_AN, sa->an);
402*de1e4e89SAndroid Build Coastguard Worker
403*de1e4e89SAndroid Build Coastguard Worker if (c != CMD_DEL) {
404*de1e4e89SAndroid Build Coastguard Worker if (sa->pn)
405*de1e4e89SAndroid Build Coastguard Worker addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN,
406*de1e4e89SAndroid Build Coastguard Worker sa->pn);
407*de1e4e89SAndroid Build Coastguard Worker
408*de1e4e89SAndroid Build Coastguard Worker if (sa->key_len) {
409*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEYID,
410*de1e4e89SAndroid Build Coastguard Worker sa->key_id, MACSEC_KEYID_LEN);
411*de1e4e89SAndroid Build Coastguard Worker addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEY,
412*de1e4e89SAndroid Build Coastguard Worker sa->key, sa->key_len);
413*de1e4e89SAndroid Build Coastguard Worker }
414*de1e4e89SAndroid Build Coastguard Worker
415*de1e4e89SAndroid Build Coastguard Worker if (sa->active != 0xff) {
416*de1e4e89SAndroid Build Coastguard Worker addattr8(&req.n, MACSEC_BUFLEN,
417*de1e4e89SAndroid Build Coastguard Worker MACSEC_SA_ATTR_ACTIVE, sa->active);
418*de1e4e89SAndroid Build Coastguard Worker }
419*de1e4e89SAndroid Build Coastguard Worker }
420*de1e4e89SAndroid Build Coastguard Worker
421*de1e4e89SAndroid Build Coastguard Worker addattr_nest_end(&req.n, attr_sa);
422*de1e4e89SAndroid Build Coastguard Worker
423*de1e4e89SAndroid Build Coastguard Worker talk:
424*de1e4e89SAndroid Build Coastguard Worker if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
425*de1e4e89SAndroid Build Coastguard Worker return -2;
426*de1e4e89SAndroid Build Coastguard Worker
427*de1e4e89SAndroid Build Coastguard Worker return 0;
428*de1e4e89SAndroid Build Coastguard Worker }
429*de1e4e89SAndroid Build Coastguard Worker
check_sa_args(enum cmd c,struct sa_desc * sa)430*de1e4e89SAndroid Build Coastguard Worker static bool check_sa_args(enum cmd c, struct sa_desc *sa)
431*de1e4e89SAndroid Build Coastguard Worker {
432*de1e4e89SAndroid Build Coastguard Worker if (c == CMD_ADD) {
433*de1e4e89SAndroid Build Coastguard Worker if (!sa->key_len) {
434*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "cannot create SA without key\n");
435*de1e4e89SAndroid Build Coastguard Worker return -1;
436*de1e4e89SAndroid Build Coastguard Worker }
437*de1e4e89SAndroid Build Coastguard Worker
438*de1e4e89SAndroid Build Coastguard Worker if (sa->pn == 0) {
439*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "must specify a packet number != 0\n");
440*de1e4e89SAndroid Build Coastguard Worker return -1;
441*de1e4e89SAndroid Build Coastguard Worker }
442*de1e4e89SAndroid Build Coastguard Worker } else if (c == CMD_UPD) {
443*de1e4e89SAndroid Build Coastguard Worker if (sa->key_len) {
444*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "cannot change key on SA\n");
445*de1e4e89SAndroid Build Coastguard Worker return -1;
446*de1e4e89SAndroid Build Coastguard Worker }
447*de1e4e89SAndroid Build Coastguard Worker }
448*de1e4e89SAndroid Build Coastguard Worker
449*de1e4e89SAndroid Build Coastguard Worker return 0;
450*de1e4e89SAndroid Build Coastguard Worker }
451*de1e4e89SAndroid Build Coastguard Worker
do_modify_txsa(enum cmd c,int argc,char ** argv,int ifindex)452*de1e4e89SAndroid Build Coastguard Worker static int do_modify_txsa(enum cmd c, int argc, char **argv, int ifindex)
453*de1e4e89SAndroid Build Coastguard Worker {
454*de1e4e89SAndroid Build Coastguard Worker struct sa_desc txsa = {0};
455*de1e4e89SAndroid Build Coastguard Worker enum macsec_nl_commands cmd;
456*de1e4e89SAndroid Build Coastguard Worker
457*de1e4e89SAndroid Build Coastguard Worker txsa.an = 0xff;
458*de1e4e89SAndroid Build Coastguard Worker txsa.active = 0xff;
459*de1e4e89SAndroid Build Coastguard Worker
460*de1e4e89SAndroid Build Coastguard Worker if (argc == 0 || !get_sa(&argc, &argv, &txsa.an))
461*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
462*de1e4e89SAndroid Build Coastguard Worker
463*de1e4e89SAndroid Build Coastguard Worker if (c == CMD_DEL)
464*de1e4e89SAndroid Build Coastguard Worker goto modify;
465*de1e4e89SAndroid Build Coastguard Worker
466*de1e4e89SAndroid Build Coastguard Worker if (parse_sa_args(&argc, &argv, &txsa))
467*de1e4e89SAndroid Build Coastguard Worker return -1;
468*de1e4e89SAndroid Build Coastguard Worker
469*de1e4e89SAndroid Build Coastguard Worker if (check_sa_args(c, &txsa))
470*de1e4e89SAndroid Build Coastguard Worker return -1;
471*de1e4e89SAndroid Build Coastguard Worker
472*de1e4e89SAndroid Build Coastguard Worker modify:
473*de1e4e89SAndroid Build Coastguard Worker cmd = macsec_commands[c][1][0];
474*de1e4e89SAndroid Build Coastguard Worker return do_modify_nl(c, cmd, ifindex, NULL, &txsa);
475*de1e4e89SAndroid Build Coastguard Worker }
476*de1e4e89SAndroid Build Coastguard Worker
do_modify_rxsci(enum cmd c,int argc,char ** argv,int ifindex)477*de1e4e89SAndroid Build Coastguard Worker static int do_modify_rxsci(enum cmd c, int argc, char **argv, int ifindex)
478*de1e4e89SAndroid Build Coastguard Worker {
479*de1e4e89SAndroid Build Coastguard Worker struct rxsc_desc rxsc = {0};
480*de1e4e89SAndroid Build Coastguard Worker struct sa_desc rxsa = {0};
481*de1e4e89SAndroid Build Coastguard Worker bool sa_set;
482*de1e4e89SAndroid Build Coastguard Worker enum macsec_nl_commands cmd;
483*de1e4e89SAndroid Build Coastguard Worker
484*de1e4e89SAndroid Build Coastguard Worker rxsc.ifindex = ifindex;
485*de1e4e89SAndroid Build Coastguard Worker rxsc.active = 0xff;
486*de1e4e89SAndroid Build Coastguard Worker rxsa.an = 0xff;
487*de1e4e89SAndroid Build Coastguard Worker rxsa.active = 0xff;
488*de1e4e89SAndroid Build Coastguard Worker
489*de1e4e89SAndroid Build Coastguard Worker sa_set = parse_rxsci(&argc, &argv, &rxsc, &rxsa);
490*de1e4e89SAndroid Build Coastguard Worker
491*de1e4e89SAndroid Build Coastguard Worker if (c == CMD_DEL)
492*de1e4e89SAndroid Build Coastguard Worker goto modify;
493*de1e4e89SAndroid Build Coastguard Worker
494*de1e4e89SAndroid Build Coastguard Worker if (sa_set && (parse_sa_args(&argc, &argv, &rxsa) ||
495*de1e4e89SAndroid Build Coastguard Worker check_sa_args(c, &rxsa)))
496*de1e4e89SAndroid Build Coastguard Worker return -1;
497*de1e4e89SAndroid Build Coastguard Worker if (!sa_set && parse_rxsci_args(&argc, &argv, &rxsc))
498*de1e4e89SAndroid Build Coastguard Worker return -1;
499*de1e4e89SAndroid Build Coastguard Worker
500*de1e4e89SAndroid Build Coastguard Worker modify:
501*de1e4e89SAndroid Build Coastguard Worker cmd = macsec_commands[c][sa_set][1];
502*de1e4e89SAndroid Build Coastguard Worker return do_modify_nl(c, cmd, rxsc.ifindex, &rxsc, &rxsa);
503*de1e4e89SAndroid Build Coastguard Worker }
504*de1e4e89SAndroid Build Coastguard Worker
do_modify(enum cmd c,int argc,char ** argv)505*de1e4e89SAndroid Build Coastguard Worker static int do_modify(enum cmd c, int argc, char **argv)
506*de1e4e89SAndroid Build Coastguard Worker {
507*de1e4e89SAndroid Build Coastguard Worker int ifindex;
508*de1e4e89SAndroid Build Coastguard Worker
509*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
510*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
511*de1e4e89SAndroid Build Coastguard Worker
512*de1e4e89SAndroid Build Coastguard Worker ifindex = ll_name_to_index(*argv);
513*de1e4e89SAndroid Build Coastguard Worker if (!ifindex) {
514*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Device \"%s\" does not exist.\n", *argv);
515*de1e4e89SAndroid Build Coastguard Worker return -1;
516*de1e4e89SAndroid Build Coastguard Worker }
517*de1e4e89SAndroid Build Coastguard Worker argc--; argv++;
518*de1e4e89SAndroid Build Coastguard Worker
519*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
520*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
521*de1e4e89SAndroid Build Coastguard Worker
522*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "tx") == 0)
523*de1e4e89SAndroid Build Coastguard Worker return do_modify_txsa(c, argc-1, argv+1, ifindex);
524*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "rx") == 0)
525*de1e4e89SAndroid Build Coastguard Worker return do_modify_rxsci(c, argc-1, argv+1, ifindex);
526*de1e4e89SAndroid Build Coastguard Worker
527*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
528*de1e4e89SAndroid Build Coastguard Worker return -1;
529*de1e4e89SAndroid Build Coastguard Worker }
530*de1e4e89SAndroid Build Coastguard Worker
531*de1e4e89SAndroid Build Coastguard Worker /* dump/show */
532*de1e4e89SAndroid Build Coastguard Worker static struct {
533*de1e4e89SAndroid Build Coastguard Worker int ifindex;
534*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
535*de1e4e89SAndroid Build Coastguard Worker } filter;
536*de1e4e89SAndroid Build Coastguard Worker
validate_dump(struct rtattr ** attrs)537*de1e4e89SAndroid Build Coastguard Worker static int validate_dump(struct rtattr **attrs)
538*de1e4e89SAndroid Build Coastguard Worker {
539*de1e4e89SAndroid Build Coastguard Worker return attrs[MACSEC_ATTR_IFINDEX] && attrs[MACSEC_ATTR_SECY] &&
540*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_TXSA_LIST] && attrs[MACSEC_ATTR_RXSC_LIST] &&
541*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_TXSC_STATS] && attrs[MACSEC_ATTR_SECY_STATS];
542*de1e4e89SAndroid Build Coastguard Worker
543*de1e4e89SAndroid Build Coastguard Worker }
544*de1e4e89SAndroid Build Coastguard Worker
validate_secy_dump(struct rtattr ** attrs)545*de1e4e89SAndroid Build Coastguard Worker static int validate_secy_dump(struct rtattr **attrs)
546*de1e4e89SAndroid Build Coastguard Worker {
547*de1e4e89SAndroid Build Coastguard Worker return attrs[MACSEC_SECY_ATTR_SCI] &&
548*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_ENCODING_SA] &&
549*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] &&
550*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_ICV_LEN] &&
551*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_PROTECT] &&
552*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_REPLAY] &&
553*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_OPER] &&
554*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_VALIDATE] &&
555*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_ENCRYPT] &&
556*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_INC_SCI] &&
557*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_ES] &&
558*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_SCB];
559*de1e4e89SAndroid Build Coastguard Worker }
560*de1e4e89SAndroid Build Coastguard Worker
print_flag(FILE * f,struct rtattr * attrs[],const char * desc,int field)561*de1e4e89SAndroid Build Coastguard Worker static void print_flag(FILE *f, struct rtattr *attrs[], const char *desc,
562*de1e4e89SAndroid Build Coastguard Worker int field)
563*de1e4e89SAndroid Build Coastguard Worker {
564*de1e4e89SAndroid Build Coastguard Worker if (attrs[field]) {
565*de1e4e89SAndroid Build Coastguard Worker const char *v = values_on_off[!!rta_getattr_u8(attrs[field])];
566*de1e4e89SAndroid Build Coastguard Worker
567*de1e4e89SAndroid Build Coastguard Worker if (is_json_context())
568*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_JSON, desc, NULL, v);
569*de1e4e89SAndroid Build Coastguard Worker else
570*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "%s %s ", desc, v);
571*de1e4e89SAndroid Build Coastguard Worker }
572*de1e4e89SAndroid Build Coastguard Worker }
573*de1e4e89SAndroid Build Coastguard Worker
574*de1e4e89SAndroid Build Coastguard Worker #define DEFAULT_CIPHER_NAME "GCM-AES-128"
575*de1e4e89SAndroid Build Coastguard Worker
cs_id_to_name(__u64 cid)576*de1e4e89SAndroid Build Coastguard Worker static const char *cs_id_to_name(__u64 cid)
577*de1e4e89SAndroid Build Coastguard Worker {
578*de1e4e89SAndroid Build Coastguard Worker switch (cid) {
579*de1e4e89SAndroid Build Coastguard Worker case MACSEC_DEFAULT_CIPHER_ID:
580*de1e4e89SAndroid Build Coastguard Worker case MACSEC_DEFAULT_CIPHER_ALT:
581*de1e4e89SAndroid Build Coastguard Worker return DEFAULT_CIPHER_NAME;
582*de1e4e89SAndroid Build Coastguard Worker default:
583*de1e4e89SAndroid Build Coastguard Worker return "(unknown)";
584*de1e4e89SAndroid Build Coastguard Worker }
585*de1e4e89SAndroid Build Coastguard Worker }
586*de1e4e89SAndroid Build Coastguard Worker
print_cipher_suite(const char * prefix,__u64 cid,__u8 icv_len)587*de1e4e89SAndroid Build Coastguard Worker static void print_cipher_suite(const char *prefix, __u64 cid, __u8 icv_len)
588*de1e4e89SAndroid Build Coastguard Worker {
589*de1e4e89SAndroid Build Coastguard Worker printf("%scipher suite: %s, using ICV length %d\n", prefix,
590*de1e4e89SAndroid Build Coastguard Worker cs_id_to_name(cid), icv_len);
591*de1e4e89SAndroid Build Coastguard Worker }
592*de1e4e89SAndroid Build Coastguard Worker
print_attrs(const char * prefix,struct rtattr * attrs[])593*de1e4e89SAndroid Build Coastguard Worker static void print_attrs(const char *prefix, struct rtattr *attrs[])
594*de1e4e89SAndroid Build Coastguard Worker {
595*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "protect", MACSEC_SECY_ATTR_PROTECT);
596*de1e4e89SAndroid Build Coastguard Worker
597*de1e4e89SAndroid Build Coastguard Worker if (attrs[MACSEC_SECY_ATTR_VALIDATE]) {
598*de1e4e89SAndroid Build Coastguard Worker __u8 val = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_VALIDATE]);
599*de1e4e89SAndroid Build Coastguard Worker
600*de1e4e89SAndroid Build Coastguard Worker printf("validate %s ", VALIDATE_STR[val]);
601*de1e4e89SAndroid Build Coastguard Worker }
602*de1e4e89SAndroid Build Coastguard Worker
603*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE);
604*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "sa", MACSEC_SA_ATTR_ACTIVE);
605*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT);
606*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI);
607*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "end_station", MACSEC_SECY_ATTR_ES);
608*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "scb", MACSEC_SECY_ATTR_SCB);
609*de1e4e89SAndroid Build Coastguard Worker
610*de1e4e89SAndroid Build Coastguard Worker print_flag(stdout, attrs, "replay", MACSEC_SECY_ATTR_REPLAY);
611*de1e4e89SAndroid Build Coastguard Worker if (attrs[MACSEC_SECY_ATTR_WINDOW]) {
612*de1e4e89SAndroid Build Coastguard Worker printf("window %d ",
613*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW]));
614*de1e4e89SAndroid Build Coastguard Worker }
615*de1e4e89SAndroid Build Coastguard Worker
616*de1e4e89SAndroid Build Coastguard Worker if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] &&
617*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_SECY_ATTR_ICV_LEN]) {
618*de1e4e89SAndroid Build Coastguard Worker printf("\n");
619*de1e4e89SAndroid Build Coastguard Worker print_cipher_suite(prefix,
620*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]),
621*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN]));
622*de1e4e89SAndroid Build Coastguard Worker }
623*de1e4e89SAndroid Build Coastguard Worker
624*de1e4e89SAndroid Build Coastguard Worker }
625*de1e4e89SAndroid Build Coastguard Worker
print_one_stat(const char ** names,struct rtattr ** attr,int idx,bool long_stat)626*de1e4e89SAndroid Build Coastguard Worker static void print_one_stat(const char **names, struct rtattr **attr, int idx,
627*de1e4e89SAndroid Build Coastguard Worker bool long_stat)
628*de1e4e89SAndroid Build Coastguard Worker {
629*de1e4e89SAndroid Build Coastguard Worker int pad = strlen(names[idx]) + 1;
630*de1e4e89SAndroid Build Coastguard Worker
631*de1e4e89SAndroid Build Coastguard Worker if (attr[idx]) {
632*de1e4e89SAndroid Build Coastguard Worker if (long_stat)
633*de1e4e89SAndroid Build Coastguard Worker printf("%*llu", pad, rta_getattr_u64(attr[idx]));
634*de1e4e89SAndroid Build Coastguard Worker else
635*de1e4e89SAndroid Build Coastguard Worker printf("%*u", pad, rta_getattr_u32(attr[idx]));
636*de1e4e89SAndroid Build Coastguard Worker } else {
637*de1e4e89SAndroid Build Coastguard Worker printf("%*c", pad, '-');
638*de1e4e89SAndroid Build Coastguard Worker }
639*de1e4e89SAndroid Build Coastguard Worker }
640*de1e4e89SAndroid Build Coastguard Worker
641*de1e4e89SAndroid Build Coastguard Worker static const char *txsc_stats_names[NUM_MACSEC_TXSC_STATS_ATTR] = {
642*de1e4e89SAndroid Build Coastguard Worker [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected",
643*de1e4e89SAndroid Build Coastguard Worker [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted",
644*de1e4e89SAndroid Build Coastguard Worker [MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED] = "OutOctetsProtected",
645*de1e4e89SAndroid Build Coastguard Worker [MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED] = "OutOctetsEncrypted",
646*de1e4e89SAndroid Build Coastguard Worker };
647*de1e4e89SAndroid Build Coastguard Worker
print_txsc_stats(const char * prefix,struct rtattr * attr)648*de1e4e89SAndroid Build Coastguard Worker static void print_txsc_stats(const char *prefix, struct rtattr *attr)
649*de1e4e89SAndroid Build Coastguard Worker {
650*de1e4e89SAndroid Build Coastguard Worker struct rtattr *stats[MACSEC_TXSC_STATS_ATTR_MAX + 1];
651*de1e4e89SAndroid Build Coastguard Worker int i;
652*de1e4e89SAndroid Build Coastguard Worker
653*de1e4e89SAndroid Build Coastguard Worker if (!attr || show_stats == 0)
654*de1e4e89SAndroid Build Coastguard Worker return;
655*de1e4e89SAndroid Build Coastguard Worker
656*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(stats, MACSEC_TXSC_STATS_ATTR_MAX, attr);
657*de1e4e89SAndroid Build Coastguard Worker printf("%sstats:", prefix);
658*de1e4e89SAndroid Build Coastguard Worker
659*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_TXSC_STATS_ATTR; i++) {
660*de1e4e89SAndroid Build Coastguard Worker if (!txsc_stats_names[i])
661*de1e4e89SAndroid Build Coastguard Worker continue;
662*de1e4e89SAndroid Build Coastguard Worker printf(" %s", txsc_stats_names[i]);
663*de1e4e89SAndroid Build Coastguard Worker }
664*de1e4e89SAndroid Build Coastguard Worker
665*de1e4e89SAndroid Build Coastguard Worker printf("\n%s ", prefix);
666*de1e4e89SAndroid Build Coastguard Worker
667*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_TXSC_STATS_ATTR; i++) {
668*de1e4e89SAndroid Build Coastguard Worker if (!txsc_stats_names[i])
669*de1e4e89SAndroid Build Coastguard Worker continue;
670*de1e4e89SAndroid Build Coastguard Worker print_one_stat(txsc_stats_names, stats, i, true);
671*de1e4e89SAndroid Build Coastguard Worker }
672*de1e4e89SAndroid Build Coastguard Worker
673*de1e4e89SAndroid Build Coastguard Worker printf("\n");
674*de1e4e89SAndroid Build Coastguard Worker }
675*de1e4e89SAndroid Build Coastguard Worker
676*de1e4e89SAndroid Build Coastguard Worker static const char *secy_stats_names[NUM_MACSEC_SECY_STATS_ATTR] = {
677*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED] = "OutPktsUntagged",
678*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED] = "InPktsUntagged",
679*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG] = "OutPktsTooLong",
680*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG] = "InPktsNoTag",
681*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG] = "InPktsBadTag",
682*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI] = "InPktsUnknownSCI",
683*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI] = "InPktsNoSCI",
684*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN] = "InPktsOverrun",
685*de1e4e89SAndroid Build Coastguard Worker };
686*de1e4e89SAndroid Build Coastguard Worker
print_secy_stats(const char * prefix,struct rtattr * attr)687*de1e4e89SAndroid Build Coastguard Worker static void print_secy_stats(const char *prefix, struct rtattr *attr)
688*de1e4e89SAndroid Build Coastguard Worker {
689*de1e4e89SAndroid Build Coastguard Worker struct rtattr *stats[MACSEC_SECY_STATS_ATTR_MAX + 1];
690*de1e4e89SAndroid Build Coastguard Worker int i;
691*de1e4e89SAndroid Build Coastguard Worker
692*de1e4e89SAndroid Build Coastguard Worker if (!attr || show_stats == 0)
693*de1e4e89SAndroid Build Coastguard Worker return;
694*de1e4e89SAndroid Build Coastguard Worker
695*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(stats, MACSEC_SECY_STATS_ATTR_MAX, attr);
696*de1e4e89SAndroid Build Coastguard Worker printf("%sstats:", prefix);
697*de1e4e89SAndroid Build Coastguard Worker
698*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_SECY_STATS_ATTR; i++) {
699*de1e4e89SAndroid Build Coastguard Worker if (!secy_stats_names[i])
700*de1e4e89SAndroid Build Coastguard Worker continue;
701*de1e4e89SAndroid Build Coastguard Worker printf(" %s", secy_stats_names[i]);
702*de1e4e89SAndroid Build Coastguard Worker }
703*de1e4e89SAndroid Build Coastguard Worker
704*de1e4e89SAndroid Build Coastguard Worker printf("\n%s ", prefix);
705*de1e4e89SAndroid Build Coastguard Worker
706*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_SECY_STATS_ATTR; i++) {
707*de1e4e89SAndroid Build Coastguard Worker if (!secy_stats_names[i])
708*de1e4e89SAndroid Build Coastguard Worker continue;
709*de1e4e89SAndroid Build Coastguard Worker print_one_stat(secy_stats_names, stats, i, true);
710*de1e4e89SAndroid Build Coastguard Worker }
711*de1e4e89SAndroid Build Coastguard Worker
712*de1e4e89SAndroid Build Coastguard Worker printf("\n");
713*de1e4e89SAndroid Build Coastguard Worker }
714*de1e4e89SAndroid Build Coastguard Worker
715*de1e4e89SAndroid Build Coastguard Worker static const char *rxsa_stats_names[NUM_MACSEC_SA_STATS_ATTR] = {
716*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_IN_PKTS_OK] = "InPktsOK",
717*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_IN_PKTS_INVALID] = "InPktsInvalid",
718*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_VALID] = "InPktsNotValid",
719*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_USING_SA] = "InPktsNotUsingSA",
720*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_IN_PKTS_UNUSED_SA] = "InPktsUnusedSA",
721*de1e4e89SAndroid Build Coastguard Worker };
722*de1e4e89SAndroid Build Coastguard Worker
print_rxsa_stats(const char * prefix,struct rtattr * attr)723*de1e4e89SAndroid Build Coastguard Worker static void print_rxsa_stats(const char *prefix, struct rtattr *attr)
724*de1e4e89SAndroid Build Coastguard Worker {
725*de1e4e89SAndroid Build Coastguard Worker struct rtattr *stats[MACSEC_SA_STATS_ATTR_MAX + 1];
726*de1e4e89SAndroid Build Coastguard Worker int i;
727*de1e4e89SAndroid Build Coastguard Worker
728*de1e4e89SAndroid Build Coastguard Worker if (!attr || show_stats == 0)
729*de1e4e89SAndroid Build Coastguard Worker return;
730*de1e4e89SAndroid Build Coastguard Worker
731*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX, attr);
732*de1e4e89SAndroid Build Coastguard Worker printf("%s%s ", prefix, prefix);
733*de1e4e89SAndroid Build Coastguard Worker
734*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_SA_STATS_ATTR; i++) {
735*de1e4e89SAndroid Build Coastguard Worker if (!rxsa_stats_names[i])
736*de1e4e89SAndroid Build Coastguard Worker continue;
737*de1e4e89SAndroid Build Coastguard Worker printf(" %s", rxsa_stats_names[i]);
738*de1e4e89SAndroid Build Coastguard Worker }
739*de1e4e89SAndroid Build Coastguard Worker
740*de1e4e89SAndroid Build Coastguard Worker printf("\n%s%s ", prefix, prefix);
741*de1e4e89SAndroid Build Coastguard Worker
742*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_SA_STATS_ATTR; i++) {
743*de1e4e89SAndroid Build Coastguard Worker if (!rxsa_stats_names[i])
744*de1e4e89SAndroid Build Coastguard Worker continue;
745*de1e4e89SAndroid Build Coastguard Worker print_one_stat(rxsa_stats_names, stats, i, false);
746*de1e4e89SAndroid Build Coastguard Worker }
747*de1e4e89SAndroid Build Coastguard Worker
748*de1e4e89SAndroid Build Coastguard Worker printf("\n");
749*de1e4e89SAndroid Build Coastguard Worker }
750*de1e4e89SAndroid Build Coastguard Worker
751*de1e4e89SAndroid Build Coastguard Worker static const char *txsa_stats_names[NUM_MACSEC_SA_STATS_ATTR] = {
752*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected",
753*de1e4e89SAndroid Build Coastguard Worker [MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted",
754*de1e4e89SAndroid Build Coastguard Worker };
755*de1e4e89SAndroid Build Coastguard Worker
print_txsa_stats(const char * prefix,struct rtattr * attr)756*de1e4e89SAndroid Build Coastguard Worker static void print_txsa_stats(const char *prefix, struct rtattr *attr)
757*de1e4e89SAndroid Build Coastguard Worker {
758*de1e4e89SAndroid Build Coastguard Worker struct rtattr *stats[MACSEC_SA_STATS_ATTR_MAX + 1];
759*de1e4e89SAndroid Build Coastguard Worker
760*de1e4e89SAndroid Build Coastguard Worker if (!attr || show_stats == 0)
761*de1e4e89SAndroid Build Coastguard Worker return;
762*de1e4e89SAndroid Build Coastguard Worker
763*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX, attr);
764*de1e4e89SAndroid Build Coastguard Worker printf("%s%s %s %s\n", prefix, prefix,
765*de1e4e89SAndroid Build Coastguard Worker txsa_stats_names[MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED],
766*de1e4e89SAndroid Build Coastguard Worker txsa_stats_names[MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED]);
767*de1e4e89SAndroid Build Coastguard Worker printf("%s%s ", prefix, prefix);
768*de1e4e89SAndroid Build Coastguard Worker
769*de1e4e89SAndroid Build Coastguard Worker print_one_stat(txsa_stats_names, stats,
770*de1e4e89SAndroid Build Coastguard Worker MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED, false);
771*de1e4e89SAndroid Build Coastguard Worker print_one_stat(txsa_stats_names, stats,
772*de1e4e89SAndroid Build Coastguard Worker MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED, false);
773*de1e4e89SAndroid Build Coastguard Worker printf("\n");
774*de1e4e89SAndroid Build Coastguard Worker }
775*de1e4e89SAndroid Build Coastguard Worker
print_tx_sc(const char * prefix,__u64 sci,__u8 encoding_sa,struct rtattr * txsc_stats,struct rtattr * secy_stats,struct rtattr * sa)776*de1e4e89SAndroid Build Coastguard Worker static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa,
777*de1e4e89SAndroid Build Coastguard Worker struct rtattr *txsc_stats, struct rtattr *secy_stats,
778*de1e4e89SAndroid Build Coastguard Worker struct rtattr *sa)
779*de1e4e89SAndroid Build Coastguard Worker {
780*de1e4e89SAndroid Build Coastguard Worker struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1];
781*de1e4e89SAndroid Build Coastguard Worker struct rtattr *a;
782*de1e4e89SAndroid Build Coastguard Worker int rem;
783*de1e4e89SAndroid Build Coastguard Worker
784*de1e4e89SAndroid Build Coastguard Worker printf("%sTXSC: %016llx on SA %d\n", prefix, ntohll(sci), encoding_sa);
785*de1e4e89SAndroid Build Coastguard Worker print_secy_stats(prefix, secy_stats);
786*de1e4e89SAndroid Build Coastguard Worker print_txsc_stats(prefix, txsc_stats);
787*de1e4e89SAndroid Build Coastguard Worker
788*de1e4e89SAndroid Build Coastguard Worker rem = RTA_PAYLOAD(sa);
789*de1e4e89SAndroid Build Coastguard Worker for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
790*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(keyid);
791*de1e4e89SAndroid Build Coastguard Worker bool state;
792*de1e4e89SAndroid Build Coastguard Worker
793*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX, a);
794*de1e4e89SAndroid Build Coastguard Worker state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]);
795*de1e4e89SAndroid Build Coastguard Worker printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix,
796*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]),
797*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]),
798*de1e4e89SAndroid Build Coastguard Worker values_on_off[state],
799*de1e4e89SAndroid Build Coastguard Worker hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]),
800*de1e4e89SAndroid Build Coastguard Worker RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]),
801*de1e4e89SAndroid Build Coastguard Worker keyid, sizeof(keyid)));
802*de1e4e89SAndroid Build Coastguard Worker print_txsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]);
803*de1e4e89SAndroid Build Coastguard Worker }
804*de1e4e89SAndroid Build Coastguard Worker }
805*de1e4e89SAndroid Build Coastguard Worker
806*de1e4e89SAndroid Build Coastguard Worker static const char *rxsc_stats_names[NUM_MACSEC_RXSC_STATS_ATTR] = {
807*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED] = "InOctetsValidated",
808*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED] = "InOctetsDecrypted",
809*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED] = "InPktsUnchecked",
810*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED] = "InPktsDelayed",
811*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK] = "InPktsOK",
812*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID] = "InPktsInvalid",
813*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE] = "InPktsLate",
814*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID] = "InPktsNotValid",
815*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA] = "InPktsNotUsingSA",
816*de1e4e89SAndroid Build Coastguard Worker [MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA] = "InPktsUnusedSA",
817*de1e4e89SAndroid Build Coastguard Worker };
818*de1e4e89SAndroid Build Coastguard Worker
print_rxsc_stats(const char * prefix,struct rtattr * attr)819*de1e4e89SAndroid Build Coastguard Worker static void print_rxsc_stats(const char *prefix, struct rtattr *attr)
820*de1e4e89SAndroid Build Coastguard Worker {
821*de1e4e89SAndroid Build Coastguard Worker struct rtattr *stats[MACSEC_RXSC_STATS_ATTR_MAX + 1];
822*de1e4e89SAndroid Build Coastguard Worker int i;
823*de1e4e89SAndroid Build Coastguard Worker
824*de1e4e89SAndroid Build Coastguard Worker if (!attr || show_stats == 0)
825*de1e4e89SAndroid Build Coastguard Worker return;
826*de1e4e89SAndroid Build Coastguard Worker
827*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(stats, MACSEC_RXSC_STATS_ATTR_MAX, attr);
828*de1e4e89SAndroid Build Coastguard Worker printf("%sstats:", prefix);
829*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_RXSC_STATS_ATTR; i++) {
830*de1e4e89SAndroid Build Coastguard Worker if (!rxsc_stats_names[i])
831*de1e4e89SAndroid Build Coastguard Worker continue;
832*de1e4e89SAndroid Build Coastguard Worker printf(" %s", rxsc_stats_names[i]);
833*de1e4e89SAndroid Build Coastguard Worker }
834*de1e4e89SAndroid Build Coastguard Worker
835*de1e4e89SAndroid Build Coastguard Worker printf("\n%s ", prefix);
836*de1e4e89SAndroid Build Coastguard Worker
837*de1e4e89SAndroid Build Coastguard Worker for (i = 1; i < NUM_MACSEC_RXSC_STATS_ATTR; i++) {
838*de1e4e89SAndroid Build Coastguard Worker if (!rxsc_stats_names[i])
839*de1e4e89SAndroid Build Coastguard Worker continue;
840*de1e4e89SAndroid Build Coastguard Worker print_one_stat(rxsc_stats_names, stats, i, true);
841*de1e4e89SAndroid Build Coastguard Worker }
842*de1e4e89SAndroid Build Coastguard Worker
843*de1e4e89SAndroid Build Coastguard Worker printf("\n");
844*de1e4e89SAndroid Build Coastguard Worker }
845*de1e4e89SAndroid Build Coastguard Worker
print_rx_sc(const char * prefix,__u64 sci,__u8 active,struct rtattr * rxsc_stats,struct rtattr * sa)846*de1e4e89SAndroid Build Coastguard Worker static void print_rx_sc(const char *prefix, __u64 sci, __u8 active,
847*de1e4e89SAndroid Build Coastguard Worker struct rtattr *rxsc_stats, struct rtattr *sa)
848*de1e4e89SAndroid Build Coastguard Worker {
849*de1e4e89SAndroid Build Coastguard Worker struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1];
850*de1e4e89SAndroid Build Coastguard Worker struct rtattr *a;
851*de1e4e89SAndroid Build Coastguard Worker int rem;
852*de1e4e89SAndroid Build Coastguard Worker
853*de1e4e89SAndroid Build Coastguard Worker printf("%sRXSC: %016llx, state %s\n", prefix, ntohll(sci),
854*de1e4e89SAndroid Build Coastguard Worker values_on_off[!!active]);
855*de1e4e89SAndroid Build Coastguard Worker print_rxsc_stats(prefix, rxsc_stats);
856*de1e4e89SAndroid Build Coastguard Worker
857*de1e4e89SAndroid Build Coastguard Worker rem = RTA_PAYLOAD(sa);
858*de1e4e89SAndroid Build Coastguard Worker for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
859*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(keyid);
860*de1e4e89SAndroid Build Coastguard Worker bool state;
861*de1e4e89SAndroid Build Coastguard Worker
862*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX, a);
863*de1e4e89SAndroid Build Coastguard Worker state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]);
864*de1e4e89SAndroid Build Coastguard Worker printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix,
865*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]),
866*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]),
867*de1e4e89SAndroid Build Coastguard Worker values_on_off[state],
868*de1e4e89SAndroid Build Coastguard Worker hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]),
869*de1e4e89SAndroid Build Coastguard Worker RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]),
870*de1e4e89SAndroid Build Coastguard Worker keyid, sizeof(keyid)));
871*de1e4e89SAndroid Build Coastguard Worker print_rxsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]);
872*de1e4e89SAndroid Build Coastguard Worker }
873*de1e4e89SAndroid Build Coastguard Worker }
874*de1e4e89SAndroid Build Coastguard Worker
process(const struct sockaddr_nl * who,struct nlmsghdr * n,void * arg)875*de1e4e89SAndroid Build Coastguard Worker static int process(const struct sockaddr_nl *who, struct nlmsghdr *n,
876*de1e4e89SAndroid Build Coastguard Worker void *arg)
877*de1e4e89SAndroid Build Coastguard Worker {
878*de1e4e89SAndroid Build Coastguard Worker struct genlmsghdr *ghdr;
879*de1e4e89SAndroid Build Coastguard Worker struct rtattr *attrs[MACSEC_ATTR_MAX + 1], *sc, *c;
880*de1e4e89SAndroid Build Coastguard Worker struct rtattr *attrs_secy[MACSEC_SECY_ATTR_MAX + 1];
881*de1e4e89SAndroid Build Coastguard Worker int len = n->nlmsg_len;
882*de1e4e89SAndroid Build Coastguard Worker int ifindex;
883*de1e4e89SAndroid Build Coastguard Worker __u64 sci;
884*de1e4e89SAndroid Build Coastguard Worker __u8 encoding_sa;
885*de1e4e89SAndroid Build Coastguard Worker int rem;
886*de1e4e89SAndroid Build Coastguard Worker
887*de1e4e89SAndroid Build Coastguard Worker if (n->nlmsg_type != genl_family)
888*de1e4e89SAndroid Build Coastguard Worker return -1;
889*de1e4e89SAndroid Build Coastguard Worker
890*de1e4e89SAndroid Build Coastguard Worker len -= NLMSG_LENGTH(GENL_HDRLEN);
891*de1e4e89SAndroid Build Coastguard Worker if (len < 0)
892*de1e4e89SAndroid Build Coastguard Worker return -1;
893*de1e4e89SAndroid Build Coastguard Worker
894*de1e4e89SAndroid Build Coastguard Worker ghdr = NLMSG_DATA(n);
895*de1e4e89SAndroid Build Coastguard Worker if (ghdr->cmd != MACSEC_CMD_GET_TXSC)
896*de1e4e89SAndroid Build Coastguard Worker return 0;
897*de1e4e89SAndroid Build Coastguard Worker
898*de1e4e89SAndroid Build Coastguard Worker parse_rtattr(attrs, MACSEC_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
899*de1e4e89SAndroid Build Coastguard Worker if (!validate_dump(attrs)) {
900*de1e4e89SAndroid Build Coastguard Worker printf("incomplete dump message\n");
901*de1e4e89SAndroid Build Coastguard Worker return -1;
902*de1e4e89SAndroid Build Coastguard Worker }
903*de1e4e89SAndroid Build Coastguard Worker
904*de1e4e89SAndroid Build Coastguard Worker ifindex = rta_getattr_u32(attrs[MACSEC_ATTR_IFINDEX]);
905*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(attrs_secy, MACSEC_SECY_ATTR_MAX,
906*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_SECY]);
907*de1e4e89SAndroid Build Coastguard Worker
908*de1e4e89SAndroid Build Coastguard Worker if (!validate_secy_dump(attrs_secy)) {
909*de1e4e89SAndroid Build Coastguard Worker printf("incomplete dump message\n");
910*de1e4e89SAndroid Build Coastguard Worker return -1;
911*de1e4e89SAndroid Build Coastguard Worker }
912*de1e4e89SAndroid Build Coastguard Worker
913*de1e4e89SAndroid Build Coastguard Worker sci = rta_getattr_u64(attrs_secy[MACSEC_SECY_ATTR_SCI]);
914*de1e4e89SAndroid Build Coastguard Worker encoding_sa = rta_getattr_u8(attrs_secy[MACSEC_SECY_ATTR_ENCODING_SA]);
915*de1e4e89SAndroid Build Coastguard Worker
916*de1e4e89SAndroid Build Coastguard Worker if (filter.ifindex && ifindex != filter.ifindex)
917*de1e4e89SAndroid Build Coastguard Worker return 0;
918*de1e4e89SAndroid Build Coastguard Worker
919*de1e4e89SAndroid Build Coastguard Worker if (filter.sci && sci != filter.sci)
920*de1e4e89SAndroid Build Coastguard Worker return 0;
921*de1e4e89SAndroid Build Coastguard Worker
922*de1e4e89SAndroid Build Coastguard Worker printf("%d: %s: ", ifindex, ll_index_to_name(ifindex));
923*de1e4e89SAndroid Build Coastguard Worker print_attrs(" ", attrs_secy);
924*de1e4e89SAndroid Build Coastguard Worker
925*de1e4e89SAndroid Build Coastguard Worker print_tx_sc(" ", sci, encoding_sa,
926*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_TXSC_STATS],
927*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_SECY_STATS],
928*de1e4e89SAndroid Build Coastguard Worker attrs[MACSEC_ATTR_TXSA_LIST]);
929*de1e4e89SAndroid Build Coastguard Worker
930*de1e4e89SAndroid Build Coastguard Worker if (!attrs[MACSEC_ATTR_RXSC_LIST])
931*de1e4e89SAndroid Build Coastguard Worker return 0;
932*de1e4e89SAndroid Build Coastguard Worker
933*de1e4e89SAndroid Build Coastguard Worker sc = attrs[MACSEC_ATTR_RXSC_LIST];
934*de1e4e89SAndroid Build Coastguard Worker rem = RTA_PAYLOAD(sc);
935*de1e4e89SAndroid Build Coastguard Worker for (c = RTA_DATA(sc); RTA_OK(c, rem); c = RTA_NEXT(c, rem)) {
936*de1e4e89SAndroid Build Coastguard Worker struct rtattr *sc_attr[MACSEC_RXSC_ATTR_MAX + 1];
937*de1e4e89SAndroid Build Coastguard Worker
938*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX, c);
939*de1e4e89SAndroid Build Coastguard Worker print_rx_sc(" ",
940*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]),
941*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]),
942*de1e4e89SAndroid Build Coastguard Worker sc_attr[MACSEC_RXSC_ATTR_STATS],
943*de1e4e89SAndroid Build Coastguard Worker sc_attr[MACSEC_RXSC_ATTR_SA_LIST]);
944*de1e4e89SAndroid Build Coastguard Worker }
945*de1e4e89SAndroid Build Coastguard Worker
946*de1e4e89SAndroid Build Coastguard Worker return 0;
947*de1e4e89SAndroid Build Coastguard Worker }
948*de1e4e89SAndroid Build Coastguard Worker
do_dump(int ifindex)949*de1e4e89SAndroid Build Coastguard Worker static int do_dump(int ifindex)
950*de1e4e89SAndroid Build Coastguard Worker {
951*de1e4e89SAndroid Build Coastguard Worker MACSEC_GENL_REQ(req, MACSEC_BUFLEN, MACSEC_CMD_GET_TXSC,
952*de1e4e89SAndroid Build Coastguard Worker NLM_F_REQUEST | NLM_F_DUMP);
953*de1e4e89SAndroid Build Coastguard Worker
954*de1e4e89SAndroid Build Coastguard Worker memset(&filter, 0, sizeof(filter));
955*de1e4e89SAndroid Build Coastguard Worker filter.ifindex = ifindex;
956*de1e4e89SAndroid Build Coastguard Worker
957*de1e4e89SAndroid Build Coastguard Worker req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
958*de1e4e89SAndroid Build Coastguard Worker if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0) {
959*de1e4e89SAndroid Build Coastguard Worker perror("Failed to send dump request");
960*de1e4e89SAndroid Build Coastguard Worker exit(1);
961*de1e4e89SAndroid Build Coastguard Worker }
962*de1e4e89SAndroid Build Coastguard Worker
963*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) {
964*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Dump terminated\n");
965*de1e4e89SAndroid Build Coastguard Worker exit(1);
966*de1e4e89SAndroid Build Coastguard Worker }
967*de1e4e89SAndroid Build Coastguard Worker
968*de1e4e89SAndroid Build Coastguard Worker return 0;
969*de1e4e89SAndroid Build Coastguard Worker }
970*de1e4e89SAndroid Build Coastguard Worker
do_show(int argc,char ** argv)971*de1e4e89SAndroid Build Coastguard Worker static int do_show(int argc, char **argv)
972*de1e4e89SAndroid Build Coastguard Worker {
973*de1e4e89SAndroid Build Coastguard Worker int ifindex;
974*de1e4e89SAndroid Build Coastguard Worker
975*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
976*de1e4e89SAndroid Build Coastguard Worker return do_dump(0);
977*de1e4e89SAndroid Build Coastguard Worker
978*de1e4e89SAndroid Build Coastguard Worker ifindex = ll_name_to_index(*argv);
979*de1e4e89SAndroid Build Coastguard Worker if (ifindex == 0) {
980*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Device \"%s\" does not exist.\n", *argv);
981*de1e4e89SAndroid Build Coastguard Worker return -1;
982*de1e4e89SAndroid Build Coastguard Worker }
983*de1e4e89SAndroid Build Coastguard Worker
984*de1e4e89SAndroid Build Coastguard Worker argc--, argv++;
985*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
986*de1e4e89SAndroid Build Coastguard Worker return do_dump(ifindex);
987*de1e4e89SAndroid Build Coastguard Worker
988*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
989*de1e4e89SAndroid Build Coastguard Worker return -1;
990*de1e4e89SAndroid Build Coastguard Worker }
991*de1e4e89SAndroid Build Coastguard Worker
do_ipmacsec(int argc,char ** argv)992*de1e4e89SAndroid Build Coastguard Worker int do_ipmacsec(int argc, char **argv)
993*de1e4e89SAndroid Build Coastguard Worker {
994*de1e4e89SAndroid Build Coastguard Worker if (argc < 1)
995*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
996*de1e4e89SAndroid Build Coastguard Worker
997*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "help") == 0)
998*de1e4e89SAndroid Build Coastguard Worker ipmacsec_usage();
999*de1e4e89SAndroid Build Coastguard Worker
1000*de1e4e89SAndroid Build Coastguard Worker if (genl_init_handle(&genl_rth, MACSEC_GENL_NAME, &genl_family))
1001*de1e4e89SAndroid Build Coastguard Worker exit(1);
1002*de1e4e89SAndroid Build Coastguard Worker
1003*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "show") == 0)
1004*de1e4e89SAndroid Build Coastguard Worker return do_show(argc-1, argv+1);
1005*de1e4e89SAndroid Build Coastguard Worker
1006*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "add") == 0)
1007*de1e4e89SAndroid Build Coastguard Worker return do_modify(CMD_ADD, argc-1, argv+1);
1008*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "set") == 0)
1009*de1e4e89SAndroid Build Coastguard Worker return do_modify(CMD_UPD, argc-1, argv+1);
1010*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "delete") == 0)
1011*de1e4e89SAndroid Build Coastguard Worker return do_modify(CMD_DEL, argc-1, argv+1);
1012*de1e4e89SAndroid Build Coastguard Worker
1013*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Command \"%s\" is unknown, try \"ip macsec help\".\n",
1014*de1e4e89SAndroid Build Coastguard Worker *argv);
1015*de1e4e89SAndroid Build Coastguard Worker exit(-1);
1016*de1e4e89SAndroid Build Coastguard Worker }
1017*de1e4e89SAndroid Build Coastguard Worker
1018*de1e4e89SAndroid Build Coastguard Worker /* device creation */
macsec_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])1019*de1e4e89SAndroid Build Coastguard Worker static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
1020*de1e4e89SAndroid Build Coastguard Worker {
1021*de1e4e89SAndroid Build Coastguard Worker if (!tb)
1022*de1e4e89SAndroid Build Coastguard Worker return;
1023*de1e4e89SAndroid Build Coastguard Worker
1024*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_SCI]) {
1025*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
1026*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
1027*de1e4e89SAndroid Build Coastguard Worker
1028*de1e4e89SAndroid Build Coastguard Worker snprintf(b1, sizeof(b1), "%016llx",
1029*de1e4e89SAndroid Build Coastguard Worker ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
1030*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_JSON, "sci", NULL, b1);
1031*de1e4e89SAndroid Build Coastguard Worker } else {
1032*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "sci %016llx ",
1033*de1e4e89SAndroid Build Coastguard Worker ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
1034*de1e4e89SAndroid Build Coastguard Worker }
1035*de1e4e89SAndroid Build Coastguard Worker }
1036*de1e4e89SAndroid Build Coastguard Worker
1037*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, "protect", IFLA_MACSEC_PROTECT);
1038*de1e4e89SAndroid Build Coastguard Worker
1039*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
1040*de1e4e89SAndroid Build Coastguard Worker __u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
1041*de1e4e89SAndroid Build Coastguard Worker
1042*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
1043*de1e4e89SAndroid Build Coastguard Worker "cipher_suite",
1044*de1e4e89SAndroid Build Coastguard Worker "cipher %s ",
1045*de1e4e89SAndroid Build Coastguard Worker cs_id_to_name(csid));
1046*de1e4e89SAndroid Build Coastguard Worker }
1047*de1e4e89SAndroid Build Coastguard Worker
1048*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_ICV_LEN]) {
1049*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
1050*de1e4e89SAndroid Build Coastguard Worker char b2[4];
1051*de1e4e89SAndroid Build Coastguard Worker
1052*de1e4e89SAndroid Build Coastguard Worker snprintf(b2, sizeof(b2), "%hhu",
1053*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
1054*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_JSON, "icv_len", NULL, atoi(b2));
1055*de1e4e89SAndroid Build Coastguard Worker } else {
1056*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "icvlen %hhu ",
1057*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
1058*de1e4e89SAndroid Build Coastguard Worker }
1059*de1e4e89SAndroid Build Coastguard Worker }
1060*de1e4e89SAndroid Build Coastguard Worker
1061*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_ENCODING_SA]) {
1062*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
1063*de1e4e89SAndroid Build Coastguard Worker char b2[4];
1064*de1e4e89SAndroid Build Coastguard Worker
1065*de1e4e89SAndroid Build Coastguard Worker snprintf(b2, sizeof(b2), "%hhu",
1066*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
1067*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_JSON, "encoding_sa", NULL, atoi(b2));
1068*de1e4e89SAndroid Build Coastguard Worker } else {
1069*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "encodingsa %hhu ",
1070*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
1071*de1e4e89SAndroid Build Coastguard Worker }
1072*de1e4e89SAndroid Build Coastguard Worker }
1073*de1e4e89SAndroid Build Coastguard Worker
1074*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_VALIDATION]) {
1075*de1e4e89SAndroid Build Coastguard Worker __u8 val = rta_getattr_u8(tb[IFLA_MACSEC_VALIDATION]);
1076*de1e4e89SAndroid Build Coastguard Worker
1077*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
1078*de1e4e89SAndroid Build Coastguard Worker "validation",
1079*de1e4e89SAndroid Build Coastguard Worker "validate %s ",
1080*de1e4e89SAndroid Build Coastguard Worker VALIDATE_STR[val]);
1081*de1e4e89SAndroid Build Coastguard Worker }
1082*de1e4e89SAndroid Build Coastguard Worker
1083*de1e4e89SAndroid Build Coastguard Worker const char *inc_sci, *es, *replay;
1084*de1e4e89SAndroid Build Coastguard Worker
1085*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
1086*de1e4e89SAndroid Build Coastguard Worker inc_sci = "inc_sci";
1087*de1e4e89SAndroid Build Coastguard Worker replay = "replay_protect";
1088*de1e4e89SAndroid Build Coastguard Worker es = "es";
1089*de1e4e89SAndroid Build Coastguard Worker } else {
1090*de1e4e89SAndroid Build Coastguard Worker inc_sci = "send_sci";
1091*de1e4e89SAndroid Build Coastguard Worker es = "end_station";
1092*de1e4e89SAndroid Build Coastguard Worker replay = "replay";
1093*de1e4e89SAndroid Build Coastguard Worker }
1094*de1e4e89SAndroid Build Coastguard Worker
1095*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT);
1096*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, inc_sci, IFLA_MACSEC_INC_SCI);
1097*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, es, IFLA_MACSEC_ES);
1098*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, "scb", IFLA_MACSEC_SCB);
1099*de1e4e89SAndroid Build Coastguard Worker print_flag(f, tb, replay, IFLA_MACSEC_REPLAY_PROTECT);
1100*de1e4e89SAndroid Build Coastguard Worker
1101*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_MACSEC_WINDOW])
1102*de1e4e89SAndroid Build Coastguard Worker print_int(PRINT_ANY,
1103*de1e4e89SAndroid Build Coastguard Worker "window",
1104*de1e4e89SAndroid Build Coastguard Worker "window %d ",
1105*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u32(tb[IFLA_MACSEC_WINDOW]));
1106*de1e4e89SAndroid Build Coastguard Worker }
1107*de1e4e89SAndroid Build Coastguard Worker
check_txsc_flags(bool es,bool scb,bool sci)1108*de1e4e89SAndroid Build Coastguard Worker static bool check_txsc_flags(bool es, bool scb, bool sci)
1109*de1e4e89SAndroid Build Coastguard Worker {
1110*de1e4e89SAndroid Build Coastguard Worker if (sci && (es || scb))
1111*de1e4e89SAndroid Build Coastguard Worker return false;
1112*de1e4e89SAndroid Build Coastguard Worker if (es && scb)
1113*de1e4e89SAndroid Build Coastguard Worker return false;
1114*de1e4e89SAndroid Build Coastguard Worker return true;
1115*de1e4e89SAndroid Build Coastguard Worker }
1116*de1e4e89SAndroid Build Coastguard Worker
usage(FILE * f)1117*de1e4e89SAndroid Build Coastguard Worker static void usage(FILE *f)
1118*de1e4e89SAndroid Build Coastguard Worker {
1119*de1e4e89SAndroid Build Coastguard Worker fprintf(f,
1120*de1e4e89SAndroid Build Coastguard Worker "Usage: ... macsec [ [ address <lladdr> ] port { 1..2^16-1 } | sci <u64> ]\n"
1121*de1e4e89SAndroid Build Coastguard Worker " [ cipher { default | gcm-aes-128 } ]\n"
1122*de1e4e89SAndroid Build Coastguard Worker " [ icvlen { 8..16 } ]\n"
1123*de1e4e89SAndroid Build Coastguard Worker " [ encrypt { on | off } ]\n"
1124*de1e4e89SAndroid Build Coastguard Worker " [ send_sci { on | off } ]\n"
1125*de1e4e89SAndroid Build Coastguard Worker " [ end_station { on | off } ]\n"
1126*de1e4e89SAndroid Build Coastguard Worker " [ scb { on | off } ]\n"
1127*de1e4e89SAndroid Build Coastguard Worker " [ protect { on | off } ]\n"
1128*de1e4e89SAndroid Build Coastguard Worker " [ replay { on | off} window { 0..2^32-1 } ]\n"
1129*de1e4e89SAndroid Build Coastguard Worker " [ validate { strict | check | disabled } ]\n"
1130*de1e4e89SAndroid Build Coastguard Worker " [ encodingsa { 0..3 } ]\n"
1131*de1e4e89SAndroid Build Coastguard Worker );
1132*de1e4e89SAndroid Build Coastguard Worker }
1133*de1e4e89SAndroid Build Coastguard Worker
macsec_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * hdr)1134*de1e4e89SAndroid Build Coastguard Worker static int macsec_parse_opt(struct link_util *lu, int argc, char **argv,
1135*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *hdr)
1136*de1e4e89SAndroid Build Coastguard Worker {
1137*de1e4e89SAndroid Build Coastguard Worker int ret;
1138*de1e4e89SAndroid Build Coastguard Worker __u8 encoding_sa = 0xff;
1139*de1e4e89SAndroid Build Coastguard Worker __u32 window = -1;
1140*de1e4e89SAndroid Build Coastguard Worker struct cipher_args cipher = {0};
1141*de1e4e89SAndroid Build Coastguard Worker enum macsec_validation_type validate;
1142*de1e4e89SAndroid Build Coastguard Worker bool es = false, scb = false, send_sci = false;
1143*de1e4e89SAndroid Build Coastguard Worker int replay_protect = -1;
1144*de1e4e89SAndroid Build Coastguard Worker struct sci sci = { 0 };
1145*de1e4e89SAndroid Build Coastguard Worker
1146*de1e4e89SAndroid Build Coastguard Worker ret = get_sci_portaddr(&sci, &argc, &argv, true, true);
1147*de1e4e89SAndroid Build Coastguard Worker if (ret < 0) {
1148*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "expected sci\n");
1149*de1e4e89SAndroid Build Coastguard Worker return -1;
1150*de1e4e89SAndroid Build Coastguard Worker }
1151*de1e4e89SAndroid Build Coastguard Worker
1152*de1e4e89SAndroid Build Coastguard Worker if (ret > 0) {
1153*de1e4e89SAndroid Build Coastguard Worker if (sci.sci)
1154*de1e4e89SAndroid Build Coastguard Worker addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_SCI,
1155*de1e4e89SAndroid Build Coastguard Worker &sci.sci, sizeof(sci.sci));
1156*de1e4e89SAndroid Build Coastguard Worker else
1157*de1e4e89SAndroid Build Coastguard Worker addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_PORT,
1158*de1e4e89SAndroid Build Coastguard Worker &sci.port, sizeof(sci.port));
1159*de1e4e89SAndroid Build Coastguard Worker }
1160*de1e4e89SAndroid Build Coastguard Worker
1161*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
1162*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "cipher") == 0) {
1163*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1164*de1e4e89SAndroid Build Coastguard Worker if (cipher.id)
1165*de1e4e89SAndroid Build Coastguard Worker duparg("cipher", *argv);
1166*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "default") == 0 ||
1167*de1e4e89SAndroid Build Coastguard Worker strcmp(*argv, "gcm-aes-128") == 0 ||
1168*de1e4e89SAndroid Build Coastguard Worker strcmp(*argv, "GCM-AES-128") == 0)
1169*de1e4e89SAndroid Build Coastguard Worker cipher.id = MACSEC_DEFAULT_CIPHER_ID;
1170*de1e4e89SAndroid Build Coastguard Worker else
1171*de1e4e89SAndroid Build Coastguard Worker invarg("expected: default or gcm-aes-128",
1172*de1e4e89SAndroid Build Coastguard Worker *argv);
1173*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "icvlen") == 0) {
1174*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1175*de1e4e89SAndroid Build Coastguard Worker if (cipher.icv_len)
1176*de1e4e89SAndroid Build Coastguard Worker duparg("icvlen", *argv);
1177*de1e4e89SAndroid Build Coastguard Worker get_icvlen(&cipher.icv_len, *argv);
1178*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "encrypt") == 0) {
1179*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1180*de1e4e89SAndroid Build Coastguard Worker int i;
1181*de1e4e89SAndroid Build Coastguard Worker
1182*de1e4e89SAndroid Build Coastguard Worker ret = one_of("encrypt", *argv, values_on_off,
1183*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1184*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1185*de1e4e89SAndroid Build Coastguard Worker return ret;
1186*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ENCRYPT, i);
1187*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "send_sci") == 0) {
1188*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1189*de1e4e89SAndroid Build Coastguard Worker int i;
1190*de1e4e89SAndroid Build Coastguard Worker
1191*de1e4e89SAndroid Build Coastguard Worker ret = one_of("send_sci", *argv, values_on_off,
1192*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1193*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1194*de1e4e89SAndroid Build Coastguard Worker return ret;
1195*de1e4e89SAndroid Build Coastguard Worker send_sci = i;
1196*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN,
1197*de1e4e89SAndroid Build Coastguard Worker IFLA_MACSEC_INC_SCI, send_sci);
1198*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "end_station") == 0) {
1199*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1200*de1e4e89SAndroid Build Coastguard Worker int i;
1201*de1e4e89SAndroid Build Coastguard Worker
1202*de1e4e89SAndroid Build Coastguard Worker ret = one_of("end_station", *argv, values_on_off,
1203*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1204*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1205*de1e4e89SAndroid Build Coastguard Worker return ret;
1206*de1e4e89SAndroid Build Coastguard Worker es = i;
1207*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ES, es);
1208*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "scb") == 0) {
1209*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1210*de1e4e89SAndroid Build Coastguard Worker int i;
1211*de1e4e89SAndroid Build Coastguard Worker
1212*de1e4e89SAndroid Build Coastguard Worker ret = one_of("scb", *argv, values_on_off,
1213*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1214*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1215*de1e4e89SAndroid Build Coastguard Worker return ret;
1216*de1e4e89SAndroid Build Coastguard Worker scb = i;
1217*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_SCB, scb);
1218*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "protect") == 0) {
1219*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1220*de1e4e89SAndroid Build Coastguard Worker int i;
1221*de1e4e89SAndroid Build Coastguard Worker
1222*de1e4e89SAndroid Build Coastguard Worker ret = one_of("protect", *argv, values_on_off,
1223*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1224*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1225*de1e4e89SAndroid Build Coastguard Worker return ret;
1226*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_PROTECT, i);
1227*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "replay") == 0) {
1228*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1229*de1e4e89SAndroid Build Coastguard Worker int i;
1230*de1e4e89SAndroid Build Coastguard Worker
1231*de1e4e89SAndroid Build Coastguard Worker ret = one_of("replay", *argv, values_on_off,
1232*de1e4e89SAndroid Build Coastguard Worker ARRAY_SIZE(values_on_off), &i);
1233*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1234*de1e4e89SAndroid Build Coastguard Worker return ret;
1235*de1e4e89SAndroid Build Coastguard Worker replay_protect = !!i;
1236*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "window") == 0) {
1237*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1238*de1e4e89SAndroid Build Coastguard Worker ret = get_u32(&window, *argv, 0);
1239*de1e4e89SAndroid Build Coastguard Worker if (ret)
1240*de1e4e89SAndroid Build Coastguard Worker invarg("expected replay window size", *argv);
1241*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "validate") == 0) {
1242*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1243*de1e4e89SAndroid Build Coastguard Worker ret = one_of("validate", *argv,
1244*de1e4e89SAndroid Build Coastguard Worker VALIDATE_STR, ARRAY_SIZE(VALIDATE_STR),
1245*de1e4e89SAndroid Build Coastguard Worker (int *)&validate);
1246*de1e4e89SAndroid Build Coastguard Worker if (ret != 0)
1247*de1e4e89SAndroid Build Coastguard Worker return ret;
1248*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN,
1249*de1e4e89SAndroid Build Coastguard Worker IFLA_MACSEC_VALIDATION, validate);
1250*de1e4e89SAndroid Build Coastguard Worker } else if (strcmp(*argv, "encodingsa") == 0) {
1251*de1e4e89SAndroid Build Coastguard Worker if (encoding_sa != 0xff)
1252*de1e4e89SAndroid Build Coastguard Worker duparg2("encodingsa", "encodingsa");
1253*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
1254*de1e4e89SAndroid Build Coastguard Worker ret = get_an(&encoding_sa, *argv);
1255*de1e4e89SAndroid Build Coastguard Worker if (ret)
1256*de1e4e89SAndroid Build Coastguard Worker invarg("expected an { 0..3 }", *argv);
1257*de1e4e89SAndroid Build Coastguard Worker } else {
1258*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "macsec: unknown command \"%s\"?\n",
1259*de1e4e89SAndroid Build Coastguard Worker *argv);
1260*de1e4e89SAndroid Build Coastguard Worker usage(stderr);
1261*de1e4e89SAndroid Build Coastguard Worker return -1;
1262*de1e4e89SAndroid Build Coastguard Worker }
1263*de1e4e89SAndroid Build Coastguard Worker
1264*de1e4e89SAndroid Build Coastguard Worker argv++; argc--;
1265*de1e4e89SAndroid Build Coastguard Worker }
1266*de1e4e89SAndroid Build Coastguard Worker
1267*de1e4e89SAndroid Build Coastguard Worker if (!check_txsc_flags(es, scb, send_sci)) {
1268*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "invalid combination of send_sci/end_station/scb\n");
1269*de1e4e89SAndroid Build Coastguard Worker return -1;
1270*de1e4e89SAndroid Build Coastguard Worker }
1271*de1e4e89SAndroid Build Coastguard Worker
1272*de1e4e89SAndroid Build Coastguard Worker if (window != -1 && replay_protect == -1) {
1273*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
1274*de1e4e89SAndroid Build Coastguard Worker "replay window set, but replay protection not enabled. did you mean 'replay on window %u'?\n",
1275*de1e4e89SAndroid Build Coastguard Worker window);
1276*de1e4e89SAndroid Build Coastguard Worker return -1;
1277*de1e4e89SAndroid Build Coastguard Worker } else if (window == -1 && replay_protect == 1) {
1278*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
1279*de1e4e89SAndroid Build Coastguard Worker "replay protection enabled, but no window set. did you mean 'replay on window VALUE'?\n");
1280*de1e4e89SAndroid Build Coastguard Worker return -1;
1281*de1e4e89SAndroid Build Coastguard Worker }
1282*de1e4e89SAndroid Build Coastguard Worker
1283*de1e4e89SAndroid Build Coastguard Worker if (cipher.id)
1284*de1e4e89SAndroid Build Coastguard Worker addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_CIPHER_SUITE,
1285*de1e4e89SAndroid Build Coastguard Worker &cipher.id, sizeof(cipher.id));
1286*de1e4e89SAndroid Build Coastguard Worker if (cipher.icv_len)
1287*de1e4e89SAndroid Build Coastguard Worker addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ICV_LEN,
1288*de1e4e89SAndroid Build Coastguard Worker &cipher.icv_len, sizeof(cipher.icv_len));
1289*de1e4e89SAndroid Build Coastguard Worker
1290*de1e4e89SAndroid Build Coastguard Worker if (replay_protect != -1) {
1291*de1e4e89SAndroid Build Coastguard Worker addattr32(hdr, MACSEC_BUFLEN, IFLA_MACSEC_WINDOW, window);
1292*de1e4e89SAndroid Build Coastguard Worker addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_REPLAY_PROTECT,
1293*de1e4e89SAndroid Build Coastguard Worker replay_protect);
1294*de1e4e89SAndroid Build Coastguard Worker }
1295*de1e4e89SAndroid Build Coastguard Worker
1296*de1e4e89SAndroid Build Coastguard Worker if (encoding_sa != 0xff) {
1297*de1e4e89SAndroid Build Coastguard Worker addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ENCODING_SA,
1298*de1e4e89SAndroid Build Coastguard Worker &encoding_sa, sizeof(encoding_sa));
1299*de1e4e89SAndroid Build Coastguard Worker }
1300*de1e4e89SAndroid Build Coastguard Worker
1301*de1e4e89SAndroid Build Coastguard Worker return 0;
1302*de1e4e89SAndroid Build Coastguard Worker }
1303*de1e4e89SAndroid Build Coastguard Worker
macsec_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)1304*de1e4e89SAndroid Build Coastguard Worker static void macsec_print_help(struct link_util *lu, int argc, char **argv,
1305*de1e4e89SAndroid Build Coastguard Worker FILE *f)
1306*de1e4e89SAndroid Build Coastguard Worker {
1307*de1e4e89SAndroid Build Coastguard Worker usage(f);
1308*de1e4e89SAndroid Build Coastguard Worker }
1309*de1e4e89SAndroid Build Coastguard Worker
1310*de1e4e89SAndroid Build Coastguard Worker struct link_util macsec_link_util = {
1311*de1e4e89SAndroid Build Coastguard Worker .id = "macsec",
1312*de1e4e89SAndroid Build Coastguard Worker .maxattr = IFLA_MACSEC_MAX,
1313*de1e4e89SAndroid Build Coastguard Worker .parse_opt = macsec_parse_opt,
1314*de1e4e89SAndroid Build Coastguard Worker .print_help = macsec_print_help,
1315*de1e4e89SAndroid Build Coastguard Worker .print_opt = macsec_print_opt,
1316*de1e4e89SAndroid Build Coastguard Worker };
1317