To similar change as in previous one, this time for the jason (de)serialization. Re-uses the raw payload match syntax, i.e. base,offset,length. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- src/json.c | 22 ++++++++-------- src/parser_json.c | 52 ++++++++++++++++++++++++++------------ tests/py/any/tcpopt.t.json | 34 +++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/json.c b/src/json.c index 3c4654d6dada..ac3b1c833d86 100644 --- a/src/json.c +++ b/src/json.c @@ -665,30 +665,32 @@ json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx) json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx) { const char *desc = expr->exthdr.desc ? - expr->exthdr.desc->name : - "unknown-exthdr"; + expr->exthdr.desc->name : NULL; const char *field = expr->exthdr.tmpl->token; json_t *root; bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT; if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) { + static const char *offstrs[] = { "", "1", "2", "3" }; unsigned int offset = expr->exthdr.offset / 64; + const char *offstr = ""; - if (offset) { - const char *offstrs[] = { "0", "1", "2", "3" }; - const char *offstr = ""; - + if (desc) { if (offset < 4) offstr = offstrs[offset]; root = json_pack("{s:s+}", "name", desc, offstr); + + if (!is_exists) + json_object_set_new(root, "field", json_string(field)); } else { - root = json_pack("{s:s}", "name", desc); + root = json_pack("{s:i, s:i, s:i}", + "base", expr->exthdr.raw_type, + "offset", expr->exthdr.offset, + "len", expr->len); + is_exists = false; } - if (!is_exists) - json_object_set_new(root, "field", json_string(field)); - return json_pack("{s:o}", "tcp option", root); } if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) { diff --git a/src/parser_json.c b/src/parser_json.c index 6e1333659f81..b1de56a4a0d2 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -502,6 +502,8 @@ static int json_parse_tcp_option_field(int type, const char *name, int *val) return 1; desc = tcpopt_protocols[type]; + if (!desc) + return 1; for (i = 0; i < array_size(desc->templates); i++) { if (desc->templates[i].token && @@ -601,30 +603,48 @@ static struct expr *json_parse_payload_expr(struct json_ctx *ctx, static struct expr *json_parse_tcp_option_expr(struct json_ctx *ctx, const char *type, json_t *root) { + int fieldval, kind, offset, len; const char *desc, *field; - int descval, fieldval; struct expr *expr; - if (json_unpack_err(ctx, root, "{s:s}", "name", &desc)) - return NULL; - - if (json_parse_tcp_option_type(desc, &descval)) { - json_error(ctx, "Unknown tcp option name '%s'.", desc); - return NULL; - } + if (!json_unpack(root, "{s:i, s:i, s:i}", + "base", &kind, "offset", &offset, "len", &len)) { + uint32_t flag = 0; - if (json_unpack(root, "{s:s}", "field", &field)) { - expr = tcpopt_expr_alloc(int_loc, descval, + expr = tcpopt_expr_alloc(int_loc, kind, TCPOPT_COMMON_KIND); - expr->exthdr.flags = NFT_EXTHDR_F_PRESENT; + if (kind < 0 || kind > 255) + return NULL; + + if (offset == TCPOPT_COMMON_KIND && len == 8) + flag = NFT_EXTHDR_F_PRESENT; + + tcpopt_init_raw(expr, kind, offset, len, flag); return expr; + } else if (!json_unpack(root, "{s:s}", "name", &desc)) { + if (json_parse_tcp_option_type(desc, &kind)) { + json_error(ctx, "Unknown tcp option name '%s'.", desc); + return NULL; + } + + if (json_unpack(root, "{s:s}", "field", &field)) { + expr = tcpopt_expr_alloc(int_loc, kind, + TCPOPT_COMMON_KIND); + expr->exthdr.flags = NFT_EXTHDR_F_PRESENT; + return expr; + } + + if (json_parse_tcp_option_field(kind, field, &fieldval)) { + json_error(ctx, "Unknown tcp option field '%s'.", field); + return NULL; + } + + return tcpopt_expr_alloc(int_loc, kind, fieldval); } - if (json_parse_tcp_option_field(descval, field, &fieldval)) { - json_error(ctx, "Unknown tcp option field '%s'.", field); - return NULL; - } - return tcpopt_expr_alloc(int_loc, descval, fieldval); + + json_error(ctx, "Invalid tcp option expression properties."); + return NULL; } static int json_parse_ip_option_type(const char *name, int *val) diff --git a/tests/py/any/tcpopt.t.json b/tests/py/any/tcpopt.t.json index b15e36ee7f4c..139e97d8f043 100644 --- a/tests/py/any/tcpopt.t.json +++ b/tests/py/any/tcpopt.t.json @@ -414,6 +414,40 @@ } ] +# tcp option 255 missing +[ + { + "match": { + "left": { + "tcp option": { + "base": 255, + "len": 8, + "offset": 0 + } + }, + "op": "==", + "right": false + } + } +] + +# tcp option @255,8,8 255 +[ + { + "match": { + "left": { + "tcp option": { + "base": 255, + "len": 8, + "offset": 8 + } + }, + "op": "==", + "right": 255 + } + } +] + # tcp option window exists [ { -- 2.26.2