@@ -154,24 +154,29 @@ static int canid_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
if (pcfltr->can_id & CAN_EFF_FLAG) {
if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_EFF_MASK))
- fprintf(fd, "eff 0x%"PRIX32,
- pcfltr->can_id & CAN_EFF_MASK);
- else
- fprintf(fd, "eff 0x%"PRIX32":0x%"PRIX32,
- pcfltr->can_id & CAN_EFF_MASK,
- pcfltr->can_mask & CAN_EFF_MASK);
+ print_0xhex(PRINT_ANY, "eff", "eff 0x%"PRIX32,
+ pcfltr->can_id & CAN_EFF_MASK);
+ else {
+ print_0xhex(PRINT_ANY, "eff", "eff 0x%"PRIX32,
+ pcfltr->can_id & CAN_EFF_MASK);
+ print_0xhex(PRINT_ANY, "mask", ":0x%"PRIX32,
+ pcfltr->can_mask & CAN_EFF_MASK);
+ }
} else {
+
if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_SFF_MASK))
- fprintf(fd, "sff 0x%"PRIX32,
- pcfltr->can_id & CAN_SFF_MASK);
- else
- fprintf(fd, "sff 0x%"PRIX32":0x%"PRIX32,
- pcfltr->can_id & CAN_SFF_MASK,
- pcfltr->can_mask & CAN_SFF_MASK);
+ print_0xhex(PRINT_ANY, "sff", "sff 0x%"PRIX32,
+ pcfltr->can_id & CAN_SFF_MASK);
+ else {
+ print_0xhex(PRINT_ANY, "sff", "sff 0x%"PRIX32,
+ pcfltr->can_id & CAN_SFF_MASK);
+ print_0xhex(PRINT_ANY, "mask", ":0x%"PRIX32,
+ pcfltr->can_mask & CAN_SFF_MASK);
+ }
}
if ((i + 1) < rules_count)
- fprintf(fd, " ");
+ print_string(PRINT_FP, NULL, " ", NULL);
}
return 0;
@@ -138,6 +138,8 @@ static int cmp_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
int data_len)
{
struct tcf_em_cmp *cmp = data;
+ const char *align = NULL;
+ const char *op = NULL;
if (data_len < sizeof(*cmp)) {
fprintf(stderr, "CMP header size mismatch\n");
@@ -145,28 +147,36 @@ static int cmp_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
}
if (cmp->align == TCF_EM_ALIGN_U8)
- fprintf(fd, "u8 ");
+ align = "u8";
else if (cmp->align == TCF_EM_ALIGN_U16)
- fprintf(fd, "u16 ");
+ align = "u16";
else if (cmp->align == TCF_EM_ALIGN_U32)
- fprintf(fd, "u32 ");
+ align = "u32";
- fprintf(fd, "at %d layer %d ", cmp->off, cmp->layer);
+ print_uint(PRINT_JSON, "align", "%u ", cmp->align);
+ if (align)
+ print_string(PRINT_FP, NULL, "%s ", align);
+
+ print_uint(PRINT_ANY, "offset", "at %u ", cmp->off);
+ print_uint(PRINT_ANY, "layer", "layer %u ", cmp->layer);
if (cmp->mask)
- fprintf(fd, "mask 0x%x ", cmp->mask);
+ print_0xhex(PRINT_ANY, "mask", "mask 0x%x ", cmp->mask);
if (cmp->flags & TCF_EM_CMP_TRANS)
- fprintf(fd, "trans ");
+ print_null(PRINT_ANY, "trans", "trans ", NULL);
if (cmp->opnd == TCF_EM_OPND_EQ)
- fprintf(fd, "eq ");
+ op = "eq";
else if (cmp->opnd == TCF_EM_OPND_LT)
- fprintf(fd, "lt ");
+ op = "lt";
else if (cmp->opnd == TCF_EM_OPND_GT)
- fprintf(fd, "gt ");
+ op = "gt";
+
+ if (op)
+ print_string(PRINT_ANY, "opnd", "%s ", op);
- fprintf(fd, "%d", cmp->val);
+ print_uint(PRINT_ANY, "val", "%u", cmp->val);
return 0;
}
@@ -243,10 +243,15 @@ static int ipset_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
if (get_set_byid(setname, set_info->index))
return -1;
- fputs(setname, fd);
+
+ open_json_array(PRINT_ANY, setname);
+
for (i = 1; i <= set_info->dim; i++) {
- fprintf(fd, "%s%s", i == 1 ? " " : ",", set_info->flags & (1 << i) ? "src" : "dst");
+ print_string(PRINT_FP, NULL, "%s", i == 1 ? " " : ",");
+ print_string(PRINT_ANY, NULL, "%s",
+ set_info->flags & (1 << i) ? "src" : "dst");
}
+ close_json_array(PRINT_JSON, NULL);
return 0;
}
@@ -175,6 +175,12 @@ static int em_ipt_print_epot(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
const char *mname;
__u8 nfproto;
+ /* xtables-legacy doesn't support JSON print so skip it */
+ if (is_json_context()) {
+ fprintf(stderr, "xtables-legacy json not supported\n");
+ return -1;
+ }
+
if (parse_rtattr(tb, TCA_EM_IPT_MAX, data, data_len) < 0)
return -1;
@@ -406,29 +406,38 @@ static int meta_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
}
#undef PARSE_ERR
-static inline void print_binary(FILE *fd, unsigned char *str, int len)
+static void print_binary(const unsigned char *str, int len)
{
int i;
+ if (is_json_context()) {
+ open_json_array(PRINT_JSON, "data");
+
+ for (i = 0; i < len; i++)
+ print_0xhex(PRINT_JSON, NULL, NULL, str[i]);
+ close_json_array(PRINT_JSON, NULL);
+ return;
+ }
+
for (i = 0; i < len; i++)
if (!isprint(str[i]))
goto binary;
for (i = 0; i < len; i++)
- fprintf(fd, "%c", str[i]);
+ putchar(str[i]);
return;
binary:
for (i = 0; i < len; i++)
- fprintf(fd, "%02x ", str[i]);
+ printf("%02x ", str[i]);
- fprintf(fd, "\"");
+ putchar ('"');
for (i = 0; i < len; i++)
- fprintf(fd, "%c", isprint(str[i]) ? str[i] : '.');
- fprintf(fd, "\"");
+ putchar(isprint(str[i]) ? str[i] : '.');
+ putchar ('"');
}
-static inline int print_value(FILE *fd, int type, struct rtattr *rta)
+static int print_value(int type, struct rtattr *rta)
{
if (rta == NULL) {
fprintf(stderr, "Missing value TLV\n");
@@ -436,53 +445,51 @@ static inline int print_value(FILE *fd, int type, struct rtattr *rta)
}
switch (type) {
- case TCF_META_TYPE_INT:
- if (RTA_PAYLOAD(rta) < sizeof(__u32)) {
- fprintf(stderr, "meta int type value TLV " \
- "size mismatch.\n");
- return -1;
- }
- fprintf(fd, "%d", rta_getattr_u32(rta));
- break;
+ case TCF_META_TYPE_INT:
+ if (RTA_PAYLOAD(rta) < sizeof(__u32)) {
+ fprintf(stderr,
+ "meta int type value TLV size mismatch.\n");
+ return -1;
+ }
+ print_uint(PRINT_ANY, "value", "%u", rta_getattr_u32(rta));
+ break;
- case TCF_META_TYPE_VAR:
- print_binary(fd, RTA_DATA(rta), RTA_PAYLOAD(rta));
- break;
+ case TCF_META_TYPE_VAR:
+ print_binary(RTA_DATA(rta), RTA_PAYLOAD(rta));
+ break;
}
return 0;
}
-static int print_object(FILE *fd, struct tcf_meta_val *obj, struct rtattr *rta)
+static int print_object(struct tcf_meta_val *obj, struct rtattr *rta)
{
int id = TCF_META_ID(obj->kind);
int type = TCF_META_TYPE(obj->kind);
const struct meta_entry *entry;
if (id == TCF_META_ID_VALUE)
- return print_value(fd, type, rta);
+ return print_value(type, rta);
entry = lookup_meta_entry_byid(id);
if (entry == NULL)
- fprintf(fd, "[unknown meta id %d]", id);
+ print_int(PRINT_ANY, "id", "[unknown meta id %d]", id);
else
- fprintf(fd, "%s", entry->kind);
+ print_string(PRINT_ANY, "id", "%s", entry->kind);
if (obj->shift)
- fprintf(fd, " shift %d", obj->shift);
+ print_int(PRINT_ANY, "shift", " shift %d", obj->shift);
- switch (type) {
- case TCF_META_TYPE_INT:
- if (rta) {
- if (RTA_PAYLOAD(rta) < sizeof(__u32))
- goto size_mismatch;
+ if (type == TCF_META_TYPE_INT && rta) {
+ __u32 mask;
+
+ if (RTA_PAYLOAD(rta) < sizeof(__u32))
+ goto size_mismatch;
- if (rta_getattr_u32(rta))
- fprintf(fd, " mask 0x%08x",
- rta_getattr_u32(rta));
- }
- break;
+ mask = rta_getattr_u32(rta);
+ if (mask)
+ print_0xhex(PRINT_ANY, "mask", " mask 0x%08x", mask);
}
return 0;
@@ -498,6 +505,7 @@ static int meta_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
{
struct rtattr *tb[TCA_EM_META_MAX+1];
struct tcf_meta_hdr *meta_hdr;
+ const char *op = NULL;
if (parse_rtattr(tb, TCA_EM_META_MAX, data, data_len) < 0)
return -1;
@@ -514,22 +522,25 @@ static int meta_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
meta_hdr = RTA_DATA(tb[TCA_EM_META_HDR]);
- if (print_object(fd, &meta_hdr->left, tb[TCA_EM_META_LVALUE]) < 0)
+ if (print_object(&meta_hdr->left, tb[TCA_EM_META_LVALUE]) < 0)
return -1;
switch (meta_hdr->left.op) {
- case TCF_EM_OPND_EQ:
- fprintf(fd, " eq ");
- break;
- case TCF_EM_OPND_LT:
- fprintf(fd, " lt ");
- break;
- case TCF_EM_OPND_GT:
- fprintf(fd, " gt ");
- break;
+ case TCF_EM_OPND_EQ:
+ op = "eq";
+ break;
+ case TCF_EM_OPND_LT:
+ op = "lt";
+ break;
+ case TCF_EM_OPND_GT:
+ op = "gt";
+ break;
}
- return print_object(fd, &meta_hdr->right, tb[TCA_EM_META_RVALUE]);
+ if (op)
+ print_string(PRINT_ANY, "opnd", " %s ", op);
+
+ return print_object(&meta_hdr->right, tb[TCA_EM_META_RVALUE]);
}
struct ematch_util meta_ematch_util = {
@@ -116,13 +116,17 @@ static int nbyte_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
needle = data + sizeof(*nb);
+ open_json_array(PRINT_JSON, "needle");
for (i = 0; i < nb->len; i++)
- fprintf(fd, "%02x ", needle[i]);
+ print_0xhex(PRINT_ANY, NULL, "%02x ", needle[i]);
- fprintf(fd, "\"");
+ close_json_array(PRINT_ANY, "\"");
for (i = 0; i < nb->len; i++)
- fprintf(fd, "%c", isprint(needle[i]) ? needle[i] : '.');
- fprintf(fd, "\" at %d layer %d", nb->off, nb->layer);
+ print_0xhex(PRINT_FP, NULL, "%c",
+ isprint(needle[i]) ? needle[i] : '.');
+
+ print_uint(PRINT_ANY, "offset", "\" at %u ", nb->off);
+ print_uint(PRINT_ANY, "layer", "layer %u", nb->layer);
return 0;
}
@@ -153,11 +153,11 @@ static int u32_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
return -1;
}
- fprintf(fd, "%08x/%08x at %s%d",
- (unsigned int) ntohl(u_key->val),
- (unsigned int) ntohl(u_key->mask),
- u_key->offmask ? "nexthdr+" : "",
- u_key->off);
+ print_0xhex(PRINT_ANY, "val", "%08x", ntohl(u_key->val));
+ print_0xhex(PRINT_ANY, "mask", "/%08x at ", ntohl(u_key->mask));
+ if (u_key->offmask)
+ print_null(PRINT_ANY, "nexthdr", "nexthdr+", NULL);
+ print_int(PRINT_ANY, "offset", "%d", u_key->off);
return 0;
}
@@ -390,10 +390,18 @@ int parse_ematch(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
return 0;
}
+static void print_ematch_indent(int prefix)
+{
+ int n;
+
+ for (n = 0; n < prefix; n++)
+ print_string(PRINT_FP, NULL, " ", NULL);
+}
+
static int print_ematch_seq(FILE *fd, struct rtattr **tb, int start,
int prefix)
{
- int n, i = start;
+ int i = start;
struct tcf_ematch_hdr *hdr;
int dlen;
void *data;
@@ -411,7 +419,7 @@ static int print_ematch_seq(FILE *fd, struct rtattr **tb, int start,
hdr = RTA_DATA(tb[i]);
if (hdr->flags & TCF_EM_INVERT)
- fprintf(fd, "NOT ");
+ print_null(PRINT_ANY, "not", "NOT ", NULL);
if (hdr->kind == 0) {
__u32 ref;
@@ -420,40 +428,45 @@ static int print_ematch_seq(FILE *fd, struct rtattr **tb, int start,
return -1;
ref = *(__u32 *) data;
- fprintf(fd, "(\n");
- for (n = 0; n <= prefix; n++)
- fprintf(fd, " ");
+ print_string(PRINT_FP, NULL, "(%s", _SL_);
+ print_ematch_indent(prefix);
+ open_json_object("match");
+
if (print_ematch_seq(fd, tb, ref + 1, prefix + 1) < 0)
return -1;
- for (n = 0; n < prefix; n++)
- fprintf(fd, " ");
- fprintf(fd, ") ");
+
+ close_json_object();
+ print_ematch_indent(prefix);
+ print_string(PRINT_FP, NULL, ") ", NULL);
} else {
struct ematch_util *e;
e = get_ematch_kind_num(hdr->kind);
if (e == NULL)
- fprintf(fd, "[unknown ematch %d]\n",
- hdr->kind);
+ fprintf(stderr, "[unknown ematch %d]\n",
+ hdr->kind);
else {
- fprintf(fd, "%s(", e->kind);
+ print_string(PRINT_FP, NULL, "%s(", e->kind);
+ open_json_object(e->kind);
+
if (e->print_eopt(fd, hdr, data, dlen) < 0)
return -1;
- fprintf(fd, ")\n");
+
+ close_json_object();
+ print_string(PRINT_FP, NULL, ")%s", _SL_);
}
if (hdr->flags & TCF_EM_REL_MASK)
- for (n = 0; n < prefix; n++)
- fprintf(fd, " ");
+ print_ematch_indent(prefix);
}
switch (hdr->flags & TCF_EM_REL_MASK) {
case TCF_EM_REL_AND:
- fprintf(fd, "AND ");
+ print_null(PRINT_ANY, "and", "AND ", NULL);
break;
case TCF_EM_REL_OR:
- fprintf(fd, "OR ");
+ print_null(PRINT_ANY, "or", "OR ", NULL);
break;
default:
@@ -480,7 +493,7 @@ static int print_ematch_list(FILE *fd, struct tcf_ematch_tree_hdr *hdr,
if (parse_rtattr_nested(tb, hdr->nmatches, rta) < 0)
goto errout;
- fprintf(fd, "\n ");
+ print_string(PRINT_FP, NULL, "%s ", _SL_);
if (print_ematch_seq(fd, tb, 1, 1) < 0)
goto errout;
}
The ematch in filter was missing support JSON output and therefore would generate bogus output. Note: support for JSON output with ipt would be difficult to implement since xtables API doesn't have a JSON API, and anyway ipt is legacy. Therefore attempts to JSON output for ematch ipt generates an error. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> --- tc/em_canid.c | 31 +++++++++------- tc/em_cmp.c | 30 ++++++++++------ tc/em_ipset.c | 9 +++-- tc/em_ipt.c | 6 ++++ tc/em_meta.c | 99 ++++++++++++++++++++++++++++----------------------- tc/em_nbyte.c | 12 ++++--- tc/em_u32.c | 10 +++--- tc/m_ematch.c | 47 +++++++++++++++--------- 8 files changed, 149 insertions(+), 95 deletions(-)