From: Stephen Hemminger <sthem...@microsoft.com> 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 <step...@networkplumber.org> --- ip/ipmacsec.c | 249 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 168 insertions(+), 81 deletions(-) diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c index b9976da80603..38ec7136e555 100644 --- a/ip/ipmacsec.c +++ b/ip/ipmacsec.c @@ -559,19 +559,33 @@ static int validate_secy_dump(struct rtattr **attrs) 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) { - if (attrs[field]) { - const char *v = values_on_off[!!rta_getattr_u8(attrs[field])]; + __u8 flag; - if (is_json_context()) - print_string(PRINT_JSON, desc, NULL, v); - else - fprintf(f, "%s %s ", desc, v); + if (!attrs[field]) + return; + + 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" 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) -{ - printf("%scipher suite: %s, using ICV length %d\n", prefix, - cs_id_to_name(cid), icv_len); -} - -static void print_attrs(const char *prefix, struct rtattr *attrs[]) +static void print_attrs(struct rtattr *attrs[]) { - print_flag(stdout, attrs, "protect", MACSEC_SECY_ATTR_PROTECT); + print_flag(attrs, "protect", MACSEC_SECY_ATTR_PROTECT); if (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(stdout, attrs, "sa", MACSEC_SA_ATTR_ACTIVE); - print_flag(stdout, attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT); - print_flag(stdout, attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI); - print_flag(stdout, attrs, "end_station", MACSEC_SECY_ATTR_ES); - print_flag(stdout, attrs, "scb", MACSEC_SECY_ATTR_SCB); + print_flag(attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE); + print_flag(attrs, "sa", MACSEC_SA_ATTR_ACTIVE); + print_flag(attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT); + print_flag(attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI); + print_flag(attrs, "end_station", MACSEC_SECY_ATTR_ES); + 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]) { - printf("window %d ", - rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW])); + __u32 win = rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW]); + + print_uint(PRINT_ANY, "window", "window %u ", win); } - if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] && - attrs[MACSEC_SECY_ATTR_ICV_LEN]) { - printf("\n"); - print_cipher_suite(prefix, - rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]), - rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN])); + if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]) { + __u64 cid = rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]); + + print_string(PRINT_FP, NULL, "%s", _SL_); + print_string(PRINT_ANY, "cipher_suite", + " 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) @@ -642,9 +658,9 @@ static __u64 getattr_uint(struct rtattr *stat) } } -static void print_stats(const char *prefix, - const char *names[], unsigned int num, - struct rtattr *stats[]) +static void print_fp_stats(const char *prefix, + const char *names[], unsigned int num, + struct rtattr *stats[]) { unsigned int i; int pad; @@ -672,6 +688,31 @@ static void print_stats(const char *prefix, 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] = { [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected", [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; 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_txsc_stats(prefix, txsc_stats); + open_json_array(PRINT_JSON, "sa_list"); rem = RTA_PAYLOAD(sa); for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { - SPRINT_BUF(keyid); bool state; + open_json_object(NULL); parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); 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]), - rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), - values_on_off[state], - hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), - RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), - keyid, sizeof(keyid))); + + print_string(PRINT_FP, NULL, "%s", prefix); + print_string(PRINT_FP, NULL, "%s", prefix); + print_uint(PRINT_ANY, "an", "%d:", + rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN])); + print_uint(PRINT_ANY, "pn", " PN %u,", + 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]); + close_json_object(); } + close_json_array(PRINT_JSON, NULL); } 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); } -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 *sa_attr[MACSEC_SA_ATTR_MAX + 1]; struct rtattr *a; int rem; - printf("%sRXSC: %016llx, state %s\n", prefix, ntohll(sci), - values_on_off[!!active]); + print_string(PRINT_FP, NULL, "%s", prefix); + 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); + open_json_array(PRINT_JSON, "sa_list"); rem = RTA_PAYLOAD(sa); for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { - SPRINT_BUF(keyid); bool state; + open_json_object(NULL); parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); 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]), - rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), - values_on_off[state], - hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), - RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), - keyid, sizeof(keyid))); + + print_string(PRINT_FP, NULL, "%s", prefix); + print_string(PRINT_FP, NULL, "%s", prefix); + print_uint(PRINT_ANY, "an", "%u:", + rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN])); + print_uint(PRINT_ANY, "pn", " PN %u,", + 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]); + 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, void *arg) { 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]; int len = n->nlmsg_len; int ifindex; __u64 sci; __u8 encoding_sa; - int rem; if (n->nlmsg_type != genl_family) 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); if (!validate_dump(attrs)) { - printf("incomplete dump message\n"); + fprintf(stderr, "incomplete dump message\n"); return -1; } @@ -872,7 +962,7 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, attrs[MACSEC_ATTR_SECY]); if (!validate_secy_dump(attrs_secy)) { - printf("incomplete dump message\n"); + fprintf(stderr, "incomplete dump message\n"); return -1; } @@ -885,29 +975,22 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, if (filter.sci && sci != filter.sci) return 0; - printf("%d: %s: ", ifindex, ll_index_to_name(ifindex)); - print_attrs(" ", attrs_secy); + open_json_object(NULL); + 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, attrs[MACSEC_ATTR_TXSC_STATS], attrs[MACSEC_ATTR_SECY_STATS], attrs[MACSEC_ATTR_TXSA_LIST]); - if (!attrs[MACSEC_ATTR_RXSC_LIST]) - return 0; + if (attrs[MACSEC_ATTR_RXSC_LIST]) + print_rxsc_list(attrs[MACSEC_ATTR_RXSC_LIST]); - sc = attrs[MACSEC_ATTR_RXSC_LIST]; - 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]); - } + close_json_object(); return 0; } @@ -926,10 +1009,13 @@ static int do_dump(int ifindex) exit(1); } + new_json_obj(json); if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) { + delete_json_obj(); fprintf(stderr, "Dump terminated\n"); exit(1); } + delete_json_obj(); 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]) { - __u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); + __u64 csid + = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); print_string(PRINT_ANY, "cipher_suite", @@ -1058,11 +1145,11 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) replay = "replay"; } - print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT); - print_flag(f, tb, inc_sci, IFLA_MACSEC_INC_SCI); - print_flag(f, tb, es, IFLA_MACSEC_ES); - print_flag(f, tb, "scb", IFLA_MACSEC_SCB); - print_flag(f, tb, replay, IFLA_MACSEC_REPLAY_PROTECT); + print_flag(tb, "encrypt", IFLA_MACSEC_ENCRYPT); + print_flag(tb, inc_sci, IFLA_MACSEC_INC_SCI); + print_flag(tb, es, IFLA_MACSEC_ES); + print_flag(tb, "scb", IFLA_MACSEC_SCB); + print_flag(tb, replay, IFLA_MACSEC_REPLAY_PROTECT); if (tb[IFLA_MACSEC_WINDOW]) print_int(PRINT_ANY, -- 2.16.1