macsec: support JSON

The JSON support in macsec code was mostly missing and what was
there was broken. This uses new json_print utilities to complete
output.

Compile tested only.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Stephen Hemminger 2018-03-05 22:58:30 -08:00 committed by David Ahern
parent d341863839
commit c0b904de62

View File

@ -559,19 +559,33 @@ static int validate_secy_dump(struct rtattr **attrs)
attrs[MACSEC_SECY_ATTR_SCB]; attrs[MACSEC_SECY_ATTR_SCB];
} }
static void print_flag(FILE *f, struct rtattr *attrs[], const char *desc, static void print_flag(struct rtattr *attrs[], const char *desc,
int field) int field)
{ {
if (attrs[field]) { __u8 flag;
const char *v = values_on_off[!!rta_getattr_u8(attrs[field])];
if (is_json_context()) if (!attrs[field])
print_string(PRINT_JSON, desc, NULL, v); return;
else
fprintf(f, "%s %s ", desc, v); flag = rta_getattr_u8(attrs[field]);
if (is_json_context())
print_bool(PRINT_JSON, desc, NULL, flag);
else {
print_string(PRINT_FP, NULL, "%s ", desc);
print_string(PRINT_FP, NULL, "%s ",
flag ? "on" : "off");
} }
} }
static void print_key(struct rtattr *key)
{
SPRINT_BUF(keyid);
print_string(PRINT_ANY, "key", " key %s\n",
hexstring_n2a(RTA_DATA(key), RTA_PAYLOAD(key),
keyid, sizeof(keyid)));
}
#define DEFAULT_CIPHER_NAME "GCM-AES-128" #define DEFAULT_CIPHER_NAME "GCM-AES-128"
static const char *cs_id_to_name(__u64 cid) static const char *cs_id_to_name(__u64 cid)
@ -585,43 +599,45 @@ static const char *cs_id_to_name(__u64 cid)
} }
} }
static void print_cipher_suite(const char *prefix, __u64 cid, __u8 icv_len) static void print_attrs(struct rtattr *attrs[])
{ {
printf("%scipher suite: %s, using ICV length %d\n", prefix, print_flag(attrs, "protect", MACSEC_SECY_ATTR_PROTECT);
cs_id_to_name(cid), icv_len);
}
static void print_attrs(const char *prefix, struct rtattr *attrs[])
{
print_flag(stdout, attrs, "protect", MACSEC_SECY_ATTR_PROTECT);
if (attrs[MACSEC_SECY_ATTR_VALIDATE]) { if (attrs[MACSEC_SECY_ATTR_VALIDATE]) {
__u8 val = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_VALIDATE]); __u8 val = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_VALIDATE]);
printf("validate %s ", validate_str[val]); print_string(PRINT_ANY, "validate",
"validate %s ", validate_str[val]);
} }
print_flag(stdout, attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE); print_flag(attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE);
print_flag(stdout, attrs, "sa", MACSEC_SA_ATTR_ACTIVE); print_flag(attrs, "sa", MACSEC_SA_ATTR_ACTIVE);
print_flag(stdout, attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT); print_flag(attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT);
print_flag(stdout, attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI); print_flag(attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI);
print_flag(stdout, attrs, "end_station", MACSEC_SECY_ATTR_ES); print_flag(attrs, "end_station", MACSEC_SECY_ATTR_ES);
print_flag(stdout, attrs, "scb", MACSEC_SECY_ATTR_SCB); print_flag(attrs, "scb", MACSEC_SECY_ATTR_SCB);
print_flag(attrs, "replay", MACSEC_SECY_ATTR_REPLAY);
print_flag(stdout, attrs, "replay", MACSEC_SECY_ATTR_REPLAY);
if (attrs[MACSEC_SECY_ATTR_WINDOW]) { if (attrs[MACSEC_SECY_ATTR_WINDOW]) {
printf("window %d ", __u32 win = rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW]);
rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW]));
print_uint(PRINT_ANY, "window", "window %u ", win);
} }
if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] && if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]) {
attrs[MACSEC_SECY_ATTR_ICV_LEN]) { __u64 cid = rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]);
printf("\n");
print_cipher_suite(prefix, print_string(PRINT_FP, NULL, "%s", _SL_);
rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]), print_string(PRINT_ANY, "cipher_suite",
rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN])); " cipher suite: %s,", cs_id_to_name(cid));
} }
if (attrs[MACSEC_SECY_ATTR_ICV_LEN]) {
__u8 icv_len = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN]);
print_uint(PRINT_ANY, "icv_length",
" using ICV length %u\n", icv_len);
}
} }
static __u64 getattr_uint(struct rtattr *stat) static __u64 getattr_uint(struct rtattr *stat)
@ -642,9 +658,9 @@ static __u64 getattr_uint(struct rtattr *stat)
} }
} }
static void print_stats(const char *prefix, static void print_fp_stats(const char *prefix,
const char *names[], unsigned int num, const char *names[], unsigned int num,
struct rtattr *stats[]) struct rtattr *stats[])
{ {
unsigned int i; unsigned int i;
int pad; int pad;
@ -672,6 +688,31 @@ static void print_stats(const char *prefix,
printf("\n"); printf("\n");
} }
static void print_json_stats(const char *names[], unsigned int num,
struct rtattr *stats[])
{
unsigned int i;
for (i = 1; i < num; i++) {
if (!names[i] || !stats[i])
continue;
print_uint(PRINT_JSON, names[i],
NULL, getattr_uint(stats[i]));
}
}
static void print_stats(const char *prefix,
const char *names[], unsigned int num,
struct rtattr *stats[])
{
if (is_json_context())
print_json_stats(names, num, stats);
else
print_fp_stats(prefix, names, num, stats);
}
static const char *txsc_stats_names[NUM_MACSEC_TXSC_STATS_ATTR] = { static const char *txsc_stats_names[NUM_MACSEC_TXSC_STATS_ATTR] = {
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected", [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected",
[MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted", [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted",
@ -761,26 +802,40 @@ static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa,
struct rtattr *a; struct rtattr *a;
int rem; int rem;
printf("%sTXSC: %016llx on SA %d\n", prefix, ntohll(sci), encoding_sa); print_string(PRINT_FP, NULL, "%s", prefix);
print_0xhex(PRINT_ANY, "sci",
"TXSC: %016llx", ntohll(sci));
print_uint(PRINT_ANY, "encoding_sa",
" on SA %d\n", encoding_sa);
print_secy_stats(prefix, secy_stats); print_secy_stats(prefix, secy_stats);
print_txsc_stats(prefix, txsc_stats); print_txsc_stats(prefix, txsc_stats);
open_json_array(PRINT_JSON, "sa_list");
rem = RTA_PAYLOAD(sa); rem = RTA_PAYLOAD(sa);
for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
SPRINT_BUF(keyid);
bool state; bool state;
open_json_object(NULL);
parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a);
state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]);
printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix,
rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]), print_string(PRINT_FP, NULL, "%s", prefix);
rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), print_string(PRINT_FP, NULL, "%s", prefix);
values_on_off[state], print_uint(PRINT_ANY, "an", "%d:",
hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]));
RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), print_uint(PRINT_ANY, "pn", " PN %u,",
keyid, sizeof(keyid))); rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]));
print_bool(PRINT_JSON, "active", NULL, state);
print_string(PRINT_FP, NULL,
" state %s,", state ? "on" : "off");
print_key(sa_attr[MACSEC_SA_ATTR_KEYID]);
print_txsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]); print_txsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]);
close_json_object();
} }
close_json_array(PRINT_JSON, NULL);
} }
static const char *rxsc_stats_names[NUM_MACSEC_RXSC_STATS_ATTR] = { static const char *rxsc_stats_names[NUM_MACSEC_RXSC_STATS_ATTR] = {
@ -809,46 +864,81 @@ static void print_rxsc_stats(const char *prefix, struct rtattr *attr)
NUM_MACSEC_RXSC_STATS_ATTR, stats); NUM_MACSEC_RXSC_STATS_ATTR, stats);
} }
static void print_rx_sc(const char *prefix, __u64 sci, __u8 active, static void print_rx_sc(const char *prefix, __be64 sci, __u8 active,
struct rtattr *rxsc_stats, struct rtattr *sa) struct rtattr *rxsc_stats, struct rtattr *sa)
{ {
struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1]; struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1];
struct rtattr *a; struct rtattr *a;
int rem; int rem;
printf("%sRXSC: %016llx, state %s\n", prefix, ntohll(sci), print_string(PRINT_FP, NULL, "%s", prefix);
values_on_off[!!active]); print_0xhex(PRINT_ANY, "sci",
"RXSC: %016llx,", ntohll(sci));
print_bool(PRINT_JSON, "active", NULL, active);
print_string(PRINT_FP, NULL,
" state %s\n", active ? "on" : "off");
print_rxsc_stats(prefix, rxsc_stats); print_rxsc_stats(prefix, rxsc_stats);
open_json_array(PRINT_JSON, "sa_list");
rem = RTA_PAYLOAD(sa); rem = RTA_PAYLOAD(sa);
for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
SPRINT_BUF(keyid);
bool state; bool state;
open_json_object(NULL);
parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a);
state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]);
printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix,
rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]), print_string(PRINT_FP, NULL, "%s", prefix);
rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), print_string(PRINT_FP, NULL, "%s", prefix);
values_on_off[state], print_uint(PRINT_ANY, "an", "%u:",
hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]));
RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), print_uint(PRINT_ANY, "pn", " PN %u,",
keyid, sizeof(keyid))); rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]));
print_bool(PRINT_JSON, "active", NULL, state);
print_string(PRINT_FP, NULL, " state %s,",
state ? "on" : "off");
print_key(sa_attr[MACSEC_SA_ATTR_KEYID]);
print_rxsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]); print_rxsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]);
close_json_object();
} }
close_json_array(PRINT_JSON, NULL);
}
static void print_rxsc_list(struct rtattr *sc)
{
int rem = RTA_PAYLOAD(sc);
struct rtattr *c;
open_json_array(PRINT_JSON, "rx_sc");
for (c = RTA_DATA(sc); RTA_OK(c, rem); c = RTA_NEXT(c, rem)) {
struct rtattr *sc_attr[MACSEC_RXSC_ATTR_MAX + 1];
open_json_object(NULL);
parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX + 1, c);
print_rx_sc(" ",
rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]),
rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]),
sc_attr[MACSEC_RXSC_ATTR_STATS],
sc_attr[MACSEC_RXSC_ATTR_SA_LIST]);
close_json_object();
}
close_json_array(PRINT_JSON, NULL);
} }
static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, static int process(const struct sockaddr_nl *who, struct nlmsghdr *n,
void *arg) void *arg)
{ {
struct genlmsghdr *ghdr; struct genlmsghdr *ghdr;
struct rtattr *attrs[MACSEC_ATTR_MAX + 1], *sc, *c; struct rtattr *attrs[MACSEC_ATTR_MAX + 1];
struct rtattr *attrs_secy[MACSEC_SECY_ATTR_MAX + 1]; struct rtattr *attrs_secy[MACSEC_SECY_ATTR_MAX + 1];
int len = n->nlmsg_len; int len = n->nlmsg_len;
int ifindex; int ifindex;
__u64 sci; __u64 sci;
__u8 encoding_sa; __u8 encoding_sa;
int rem;
if (n->nlmsg_type != genl_family) if (n->nlmsg_type != genl_family)
return -1; return -1;
@ -863,7 +953,7 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n,
parse_rtattr(attrs, MACSEC_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); parse_rtattr(attrs, MACSEC_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
if (!validate_dump(attrs)) { if (!validate_dump(attrs)) {
printf("incomplete dump message\n"); fprintf(stderr, "incomplete dump message\n");
return -1; return -1;
} }
@ -872,7 +962,7 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n,
attrs[MACSEC_ATTR_SECY]); attrs[MACSEC_ATTR_SECY]);
if (!validate_secy_dump(attrs_secy)) { if (!validate_secy_dump(attrs_secy)) {
printf("incomplete dump message\n"); fprintf(stderr, "incomplete dump message\n");
return -1; return -1;
} }
@ -885,29 +975,22 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n,
if (filter.sci && sci != filter.sci) if (filter.sci && sci != filter.sci)
return 0; return 0;
printf("%d: %s: ", ifindex, ll_index_to_name(ifindex)); open_json_object(NULL);
print_attrs(" ", attrs_secy); print_uint(PRINT_ANY, "ifindex", "%u: ", ifindex);
print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname",
"%s: ", ll_index_to_name(ifindex));
print_attrs(attrs_secy);
print_tx_sc(" ", sci, encoding_sa, print_tx_sc(" ", sci, encoding_sa,
attrs[MACSEC_ATTR_TXSC_STATS], attrs[MACSEC_ATTR_TXSC_STATS],
attrs[MACSEC_ATTR_SECY_STATS], attrs[MACSEC_ATTR_SECY_STATS],
attrs[MACSEC_ATTR_TXSA_LIST]); attrs[MACSEC_ATTR_TXSA_LIST]);
if (!attrs[MACSEC_ATTR_RXSC_LIST]) if (attrs[MACSEC_ATTR_RXSC_LIST])
return 0; print_rxsc_list(attrs[MACSEC_ATTR_RXSC_LIST]);
sc = attrs[MACSEC_ATTR_RXSC_LIST]; close_json_object();
rem = RTA_PAYLOAD(sc);
for (c = RTA_DATA(sc); RTA_OK(c, rem); c = RTA_NEXT(c, rem)) {
struct rtattr *sc_attr[MACSEC_RXSC_ATTR_MAX + 1];
parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX + 1, c);
print_rx_sc(" ",
rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]),
rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]),
sc_attr[MACSEC_RXSC_ATTR_STATS],
sc_attr[MACSEC_RXSC_ATTR_SA_LIST]);
}
return 0; return 0;
} }
@ -926,10 +1009,13 @@ static int do_dump(int ifindex)
exit(1); exit(1);
} }
new_json_obj(json);
if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) { if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) {
delete_json_obj();
fprintf(stderr, "Dump terminated\n"); fprintf(stderr, "Dump terminated\n");
exit(1); exit(1);
} }
delete_json_obj();
return 0; return 0;
} }
@ -1000,10 +1086,11 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
} }
} }
print_flag(f, tb, "protect", IFLA_MACSEC_PROTECT); print_flag(tb, "protect", IFLA_MACSEC_PROTECT);
if (tb[IFLA_MACSEC_CIPHER_SUITE]) { if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
__u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); __u64 csid
= rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
print_string(PRINT_ANY, print_string(PRINT_ANY,
"cipher_suite", "cipher_suite",
@ -1058,11 +1145,11 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
replay = "replay"; replay = "replay";
} }
print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT); print_flag(tb, "encrypt", IFLA_MACSEC_ENCRYPT);
print_flag(f, tb, inc_sci, IFLA_MACSEC_INC_SCI); print_flag(tb, inc_sci, IFLA_MACSEC_INC_SCI);
print_flag(f, tb, es, IFLA_MACSEC_ES); print_flag(tb, es, IFLA_MACSEC_ES);
print_flag(f, tb, "scb", IFLA_MACSEC_SCB); print_flag(tb, "scb", IFLA_MACSEC_SCB);
print_flag(f, tb, replay, IFLA_MACSEC_REPLAY_PROTECT); print_flag(tb, replay, IFLA_MACSEC_REPLAY_PROTECT);
if (tb[IFLA_MACSEC_WINDOW]) if (tb[IFLA_MACSEC_WINDOW])
print_int(PRINT_ANY, print_int(PRINT_ANY,