summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2023-11-23 10:36:50 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2023-11-27 12:56:23 +0100
commitdddd8baf94e9a695753e1b7779743fe8c2b58e79 (patch)
treefa2774a875f842fbb2aa4a895098fdd35132e5cd
parent208a428a63d9292adc589ed8f6f11f561baddb65 (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.c25
-rw-r--r--src/parser_json.c91
2 files changed, 58 insertions, 58 deletions
diff --git a/src/json.c b/src/json.c
index 60315441..f167c88a 100644
--- a/src/json.c
+++ b/src/json.c
@@ -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);