diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-06-20 12:57:56 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-06-20 18:10:56 +0200 |
commit | c827a833971c14e7478ec101f998136a8cdd7bf2 (patch) | |
tree | da86ed31531c2a9a764b6714f928e52c30adfbd2 /src | |
parent | ae8786756b0ca9fd308a0089842b93dc3c329e25 (diff) |
json: add inner payload support
Add support for vxlan, geneve, gre and gretap.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/json.c | 18 | ||||
-rw-r--r-- | src/parser_json.c | 50 |
2 files changed, 62 insertions, 6 deletions
@@ -573,15 +573,23 @@ json_t *payload_expr_json(const struct expr *expr, struct output_ctx *octx) { json_t *root; - if (payload_is_known(expr)) - root = json_pack("{s:s, s:s}", - "protocol", expr->payload.desc->name, - "field", expr->payload.tmpl->token); - else + if (payload_is_known(expr)) { + if (expr->payload.inner_desc) { + root = json_pack("{s:s, s:s, s:s}", + "tunnel", expr->payload.inner_desc->name, + "protocol", expr->payload.desc->name, + "field", expr->payload.tmpl->token); + } else { + root = json_pack("{s:s, s:s}", + "protocol", expr->payload.desc->name, + "field", expr->payload.tmpl->token); + } + } else { root = json_pack("{s:s, s:i, s:i}", "base", proto_base_tokens[expr->payload.base], "offset", expr->payload.offset, "len", expr->len); + } return json_pack("{s:o}", "payload", root); } diff --git a/src/parser_json.c b/src/parser_json.c index 605dcc49..91b37b58 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -541,6 +541,27 @@ static const struct proto_desc *proto_lookup_byname(const char *name) &proto_dccp, &proto_sctp, &proto_th, + &proto_vxlan, + &proto_gre, + &proto_gretap, + &proto_geneve, + }; + unsigned int i; + + for (i = 0; i < array_size(proto_tbl); i++) { + if (!strcmp(proto_tbl[i]->name, name)) + return proto_tbl[i]; + } + return NULL; +} + +static const struct proto_desc *inner_proto_lookup_byname(const char *name) +{ + const struct proto_desc *proto_tbl[] = { + &proto_geneve, + &proto_gre, + &proto_gretap, + &proto_vxlan, }; unsigned int i; @@ -554,7 +575,7 @@ static const struct proto_desc *proto_lookup_byname(const char *name) static struct expr *json_parse_payload_expr(struct json_ctx *ctx, const char *type, json_t *root) { - const char *protocol, *field, *base; + const char *tunnel, *protocol, *field, *base; int offset, len, val; struct expr *expr; @@ -577,6 +598,33 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx, expr->byteorder = BYTEORDER_BIG_ENDIAN; expr->payload.is_raw = true; return expr; + } else if (!json_unpack(root, "{s:s, s:s, s:s}", + "tunnel", &tunnel, "protocol", &protocol, "field", &field)) { + const struct proto_desc *proto = proto_lookup_byname(protocol); + const struct proto_desc *inner_proto = inner_proto_lookup_byname(tunnel); + + if (!inner_proto) { + json_error(ctx, "Unknown payload tunnel protocol '%s'.", + tunnel); + return NULL; + } + if (!proto) { + json_error(ctx, "Unknown payload protocol '%s'.", + protocol); + return NULL; + } + if (json_parse_payload_field(proto, field, &val)) { + json_error(ctx, "Unknown %s field '%s'.", + protocol, field); + return NULL; + } + expr = payload_expr_alloc(int_loc, proto, val); + expr->payload.inner_desc = inner_proto; + + if (proto == &proto_th) + expr->payload.is_raw = true; + + return expr; } else if (!json_unpack(root, "{s:s, s:s}", "protocol", &protocol, "field", &field)) { const struct proto_desc *proto = proto_lookup_byname(protocol); |