summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-06-20 12:57:56 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2023-06-20 18:10:56 +0200
commitc827a833971c14e7478ec101f998136a8cdd7bf2 (patch)
treeda86ed31531c2a9a764b6714f928e52c30adfbd2 /src
parentae8786756b0ca9fd308a0089842b93dc3c329e25 (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.c18
-rw-r--r--src/parser_json.c50
2 files changed, 62 insertions, 6 deletions
diff --git a/src/json.c b/src/json.c
index 305eb6e3..21199ca4 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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);