diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-11-23 10:36:50 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-11-27 12:56:23 +0100 |
commit | dddd8baf94e9a695753e1b7779743fe8c2b58e79 (patch) | |
tree | fa2774a875f842fbb2aa4a895098fdd35132e5cd | |
parent | 208a428a63d9292adc589ed8f6f11f561baddb65 (diff) |
json: deal appropriately with multidevice in chain
commit 4dfb5b2010917da3f9f11c83931069931a7d6fb3 upstream.
Chain device support is broken in JSON: listing does not include devices
and parser only deals with one single device.
Use existing json_parse_flowtable_devs() function, rename it to
json_parse_devs() to parse the device array.
Use the dev_array that contains the device names (as string) for the
listing.
Update incorrect .json-nft files in tests/shell.
Fixes: 3fdc7541fba0 ("src: add multidevice support for netdev chain")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | src/json.c | 25 | ||||
-rw-r--r-- | src/parser_json.c | 91 |
2 files changed, 58 insertions, 58 deletions
@@ -247,9 +247,8 @@ static json_t *rule_print_json(struct output_ctx *octx, static json_t *chain_print_json(const struct chain *chain) { - int priority, policy, n = 0; - struct expr *dev, *expr; - json_t *root, *tmp; + json_t *root, *tmp, *devs = NULL; + int priority, policy, i; root = json_pack("{s:s, s:s, s:s, s:I}", "family", family2str(chain->handle.family), @@ -268,17 +267,19 @@ static json_t *chain_print_json(const struct chain *chain) chain->hook.num), "prio", priority, "policy", chain_policy2str(policy)); - if (chain->dev_expr) { - list_for_each_entry(expr, &chain->dev_expr->expressions, list) { - dev = expr; - n++; - } - } - if (n == 1) { - json_object_set_new(tmp, "dev", - json_string(dev->identifier)); + for (i = 0; i < chain->dev_array_len; i++) { + const char *dev = chain->dev_array[i]; + if (!devs) + devs = json_string(dev); + else if (json_is_string(devs)) + devs = json_pack("[o, s]", devs, dev); + else + json_array_append_new(devs, json_string(dev)); } + if (devs) + json_object_set_new(root, "dev", devs); + json_object_update(root, tmp); json_decref(tmp); } diff --git a/src/parser_json.c b/src/parser_json.c index 357b2d86..eb73848a 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -2897,14 +2897,49 @@ static struct expr *parse_policy(const char *policy) sizeof(int) * BITS_PER_BYTE, &policy_num); } +static struct expr *json_parse_devs(struct json_ctx *ctx, json_t *root) +{ + struct expr *tmp, *expr = compound_expr_alloc(int_loc, EXPR_LIST); + const char *dev; + json_t *value; + size_t index; + + if (!json_unpack(root, "s", &dev)) { + tmp = constant_expr_alloc(int_loc, &string_type, + BYTEORDER_HOST_ENDIAN, + strlen(dev) * BITS_PER_BYTE, dev); + compound_expr_add(expr, tmp); + return expr; + } + if (!json_is_array(root)) { + expr_free(expr); + return NULL; + } + + json_array_foreach(root, index, value) { + if (json_unpack(value, "s", &dev)) { + json_error(ctx, "Invalid device at index %zu.", + index); + expr_free(expr); + return NULL; + } + tmp = constant_expr_alloc(int_loc, &string_type, + BYTEORDER_HOST_ENDIAN, + strlen(dev) * BITS_PER_BYTE, dev); + compound_expr_add(expr, tmp); + } + return expr; +} + static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, enum cmd_ops op, enum cmd_obj obj) { struct handle h = { .table.location = *int_loc, }; - const char *family = "", *policy = "", *type, *hookstr, *name; + const char *family = "", *policy = "", *type, *hookstr; struct chain *chain; + json_t *devs = NULL; int prio; if (json_unpack_err(ctx, root, "{s:s, s:s}", @@ -2949,16 +2984,15 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root, return NULL; } - if (!json_unpack(root, "{s:s}", "dev", &name)) { - struct expr *dev_expr, *expr; + json_unpack(root, "{s:o}", "dev", &devs); - dev_expr = compound_expr_alloc(int_loc, EXPR_LIST); - expr = constant_expr_alloc(int_loc, &integer_type, - BYTEORDER_HOST_ENDIAN, - strlen(name) * BITS_PER_BYTE, - name); - compound_expr_add(dev_expr, expr); - chain->dev_expr = dev_expr; + if (devs) { + chain->dev_expr = json_parse_devs(ctx, devs); + if (!chain->dev_expr) { + json_error(ctx, "Invalid chain dev."); + chain_free(chain); + return NULL; + } } if (!json_unpack(root, "{s:s}", "policy", &policy)) { @@ -3251,41 +3285,6 @@ static struct cmd *json_parse_cmd_add_element(struct json_ctx *ctx, return cmd_alloc(op, cmd_obj, &h, int_loc, expr); } -static struct expr *json_parse_flowtable_devs(struct json_ctx *ctx, - json_t *root) -{ - struct expr *tmp, *expr = compound_expr_alloc(int_loc, EXPR_LIST); - const char *dev; - json_t *value; - size_t index; - - if (!json_unpack(root, "s", &dev)) { - tmp = constant_expr_alloc(int_loc, &string_type, - BYTEORDER_HOST_ENDIAN, - strlen(dev) * BITS_PER_BYTE, dev); - compound_expr_add(expr, tmp); - return expr; - } - if (!json_is_array(root)) { - expr_free(expr); - return NULL; - } - - json_array_foreach(root, index, value) { - if (json_unpack(value, "s", &dev)) { - json_error(ctx, "Invalid flowtable dev at index %zu.", - index); - expr_free(expr); - return NULL; - } - tmp = constant_expr_alloc(int_loc, &string_type, - BYTEORDER_HOST_ENDIAN, - strlen(dev) * BITS_PER_BYTE, dev); - compound_expr_add(expr, tmp); - } - return expr; -} - static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx, json_t *root, enum cmd_ops op, enum cmd_obj cmd_obj) @@ -3346,7 +3345,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx, sizeof(int) * BITS_PER_BYTE, &prio); if (devs) { - flowtable->dev_expr = json_parse_flowtable_devs(ctx, devs); + flowtable->dev_expr = json_parse_devs(ctx, devs); if (!flowtable->dev_expr) { json_error(ctx, "Invalid flowtable dev."); flowtable_free(flowtable); |