summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Jallot <ejallot@gmail.com>2019-10-30 18:06:19 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2019-10-31 14:16:42 +0100
commit81c51fc1ab699fb6e417ada77221657ca34efd0b (patch)
treea0deb244f9e69ba8b6013162a1293cc2ec517de2 /src
parent909e297ed430c3d7be0ad06bb002913e766115f1 (diff)
src: flowtable: add support for named flowtable listing
This patch allows you to dump a named flowtable. # nft list flowtable inet t f table inet t { flowtable f { hook ingress priority filter + 10 devices = { eth0, eth1 } } } Also: libnftables-json.adoc: fix missing quotes. Fixes: db0697ce7f60 ("src: support for flowtable listing") Fixes: 872f373dc50f ("doc: Add JSON schema documentation") Signed-off-by: Eric Jallot <ejallot@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/evaluate.c29
-rw-r--r--src/json.c20
-rw-r--r--src/mnl.c4
-rw-r--r--src/netlink.c2
-rw-r--r--src/parser_bison.y12
-rw-r--r--src/parser_json.c4
-rw-r--r--src/rule.c64
7 files changed, 122 insertions, 13 deletions
diff --git a/src/evaluate.c b/src/evaluate.c
index a56cd2a5..81230fc7 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -218,6 +218,23 @@ static int set_not_found(struct eval_ctx *ctx, const struct location *loc,
table->handle.table.name);
}
+static int flowtable_not_found(struct eval_ctx *ctx, const struct location *loc,
+ const char *ft_name)
+{
+ const struct table *table;
+ struct flowtable *ft;
+
+ ft = flowtable_lookup_fuzzy(ft_name, &ctx->nft->cache, &table);
+ if (ft == NULL)
+ return cmd_error(ctx, loc, "%s", strerror(ENOENT));
+
+ return cmd_error(ctx, loc,
+ "%s; did you mean flowtable ā€˜%sā€™ in table %s ā€˜%sā€™?",
+ strerror(ENOENT), ft->handle.flowtable.name,
+ family2str(ft->handle.family),
+ table->handle.table.name);
+}
+
/*
* Symbol expression: parse symbol and evaluate resulting expression.
*/
@@ -3834,6 +3851,7 @@ static int cmd_evaluate_list_obj(struct eval_ctx *ctx, const struct cmd *cmd,
static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
{
+ struct flowtable *ft;
struct table *table;
struct set *set;
@@ -3899,6 +3917,17 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
return chain_not_found(ctx);
return 0;
+ case CMD_OBJ_FLOWTABLE:
+ table = table_lookup(&cmd->handle, &ctx->nft->cache);
+ if (table == NULL)
+ return table_not_found(ctx);
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return flowtable_not_found(ctx, &ctx->cmd->handle.flowtable.location,
+ ctx->cmd->handle.flowtable.name);
+
+ return 0;
case CMD_OBJ_QUOTA:
return cmd_evaluate_list_obj(ctx, cmd, NFT_OBJECT_QUOTA);
case CMD_OBJ_COUNTER:
diff --git a/src/json.c b/src/json.c
index 56b20549..d079da9e 100644
--- a/src/json.c
+++ b/src/json.c
@@ -412,7 +412,7 @@ static json_t *flowtable_print_json(const struct flowtable *ftable)
BYTEORDER_HOST_ENDIAN, sizeof(int));
root = json_pack("{s:s, s:s, s:s, s:s, s:i}",
"family", family2str(ftable->handle.family),
- "name", ftable->handle.flowtable,
+ "name", ftable->handle.flowtable.name,
"table", ftable->handle.table.name,
"hook", hooknum2str(NFPROTO_NETDEV, ftable->hooknum),
"prio", priority);
@@ -1724,6 +1724,21 @@ static json_t *do_list_obj_json(struct netlink_ctx *ctx,
return root;
}
+static json_t *do_list_flowtable_json(struct netlink_ctx *ctx,
+ struct cmd *cmd, struct table *table)
+{
+ json_t *root = json_array();
+ struct flowtable *ft;
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return json_null();
+
+ json_array_append_new(root, flowtable_print_json(ft));
+
+ return root;
+}
+
static json_t *do_list_flowtables_json(struct netlink_ctx *ctx, struct cmd *cmd)
{
json_t *root = json_array(), *tmp;
@@ -1815,6 +1830,9 @@ int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_SECMARKS:
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_SECMARK);
break;
+ case CMD_OBJ_FLOWTABLE:
+ root = do_list_flowtable_json(ctx, cmd, table);
+ break;
case CMD_OBJ_FLOWTABLES:
root = do_list_flowtables_json(ctx, cmd);
break;
diff --git a/src/mnl.c b/src/mnl.c
index 933e18d9..36ccda58 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -1429,7 +1429,7 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, const struct cmd *cmd,
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE,
cmd->handle.table.name);
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME,
- cmd->handle.flowtable);
+ cmd->handle.flowtable.name);
nftnl_flowtable_set_u32(flo, NFTNL_FLOWTABLE_HOOKNUM,
cmd->flowtable->hooknum);
mpz_export_data(&priority, cmd->flowtable->priority.expr->value,
@@ -1475,7 +1475,7 @@ int mnl_nft_flowtable_del(struct netlink_ctx *ctx, const struct cmd *cmd)
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_TABLE,
cmd->handle.table.name);
nftnl_flowtable_set_str(flo, NFTNL_FLOWTABLE_NAME,
- cmd->handle.flowtable);
+ cmd->handle.flowtable.name);
nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(ctx->batch),
NFT_MSG_DELFLOWTABLE, cmd->handle.family,
diff --git a/src/netlink.c b/src/netlink.c
index c47771d3..a727c7eb 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -1131,7 +1131,7 @@ netlink_delinearize_flowtable(struct netlink_ctx *ctx,
nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY);
flowtable->handle.table.name =
xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE));
- flowtable->handle.flowtable =
+ flowtable->handle.flowtable.name =
xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME));
dev_array = nftnl_flowtable_get(nlo, NFTNL_FLOWTABLE_DEVICES);
while (dev_array[len])
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 7f9b1752..94494f6f 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -1315,6 +1315,10 @@ list_cmd : TABLE table_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_FLOWTABLES, &$2, &@$, NULL);
}
+ | FLOWTABLE flowtable_spec
+ {
+ $$ = cmd_alloc(CMD_LIST, CMD_OBJ_FLOWTABLE, &$2, &@$, NULL);
+ }
| MAPS ruleset_spec
{
$$ = cmd_alloc(CMD_LIST, CMD_OBJ_MAPS, &$2, &@$, NULL);
@@ -2224,15 +2228,17 @@ set_identifier : identifier
flowtable_spec : table_spec identifier
{
- $$ = $1;
- $$.flowtable = $2;
+ $$ = $1;
+ $$.flowtable.name = $2;
+ $$.flowtable.location = @2;
}
;
flowtable_identifier : identifier
{
memset(&$$, 0, sizeof($$));
- $$.flowtable = $1;
+ $$.flowtable.name = $1;
+ $$.flowtable.location = @1;
}
;
diff --git a/src/parser_json.c b/src/parser_json.c
index a9bcb84f..3b86a0ae 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -2967,7 +2967,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
if (json_unpack_err(ctx, root, "{s:s, s:s, s:s}",
"family", &family,
"table", &h.table.name,
- "name", &h.flowtable))
+ "name", &h.flowtable.name))
return NULL;
if (parse_family(family, &h.family)) {
@@ -2975,7 +2975,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
return NULL;
}
h.table.name = xstrdup(h.table.name);
- h.flowtable = xstrdup(h.flowtable);
+ h.flowtable.name = xstrdup(h.flowtable.name);
if (op == CMD_DELETE)
return cmd_alloc(op, cmd_obj, &h, int_loc, NULL);
diff --git a/src/rule.c b/src/rule.c
index c258f12e..a2811d18 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -105,7 +105,7 @@ void handle_free(struct handle *h)
xfree(h->table.name);
xfree(h->chain.name);
xfree(h->set.name);
- xfree(h->flowtable);
+ xfree(h->flowtable.name);
xfree(h->obj.name);
}
@@ -125,8 +125,8 @@ void handle_merge(struct handle *dst, const struct handle *src)
dst->set.name = xstrdup(src->set.name);
dst->set.location = src->set.location;
}
- if (dst->flowtable == NULL && src->flowtable != NULL)
- dst->flowtable = xstrdup(src->flowtable);
+ if (dst->flowtable.name == NULL && src->flowtable.name != NULL)
+ dst->flowtable.name = xstrdup(src->flowtable.name);
if (dst->obj.name == NULL && src->obj.name != NULL)
dst->obj.name = xstrdup(src->obj.name);
if (dst->handle.id == 0)
@@ -2156,7 +2156,7 @@ static void flowtable_print_declaration(const struct flowtable *flowtable,
if (opts->table != NULL)
nft_print(octx, " %s", opts->table);
- nft_print(octx, " %s {%s", flowtable->handle.flowtable, opts->nl);
+ nft_print(octx, " %s {%s", flowtable->handle.flowtable.name, opts->nl);
nft_print(octx, "%s%shook %s priority %s%s",
opts->tab, opts->tab,
@@ -2193,6 +2193,60 @@ void flowtable_print(const struct flowtable *s, struct output_ctx *octx)
do_flowtable_print(s, &opts, octx);
}
+struct flowtable *flowtable_lookup(const struct table *table, const char *name)
+{
+ struct flowtable *ft;
+
+ list_for_each_entry(ft, &table->flowtables, list) {
+ if (!strcmp(ft->handle.flowtable.name, name))
+ return ft;
+ }
+ return NULL;
+}
+
+struct flowtable *flowtable_lookup_fuzzy(const char *ft_name,
+ const struct nft_cache *cache,
+ const struct table **t)
+{
+ struct string_misspell_state st;
+ struct table *table;
+ struct flowtable *ft;
+
+ string_misspell_init(&st);
+
+ list_for_each_entry(table, &cache->list, list) {
+ list_for_each_entry(ft, &table->flowtables, list) {
+ if (!strcmp(ft->handle.flowtable.name, ft_name)) {
+ *t = table;
+ return ft;
+ }
+ if (string_misspell_update(ft->handle.flowtable.name,
+ ft_name, ft, &st))
+ *t = table;
+ }
+ }
+ return st.obj;
+}
+
+static int do_list_flowtable(struct netlink_ctx *ctx, struct cmd *cmd,
+ struct table *table)
+{
+ struct flowtable *ft;
+
+ ft = flowtable_lookup(table, cmd->handle.flowtable.name);
+ if (ft == NULL)
+ return -1;
+
+ nft_print(&ctx->nft->output, "table %s %s {\n",
+ family2str(table->handle.family),
+ table->handle.table.name);
+
+ flowtable_print(ft, &ctx->nft->output);
+ nft_print(&ctx->nft->output, "}\n");
+
+ return 0;
+}
+
static int do_list_flowtables(struct netlink_ctx *ctx, struct cmd *cmd)
{
struct print_fmt_options opts = {
@@ -2388,6 +2442,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_OBJ_SYNPROXY:
case CMD_OBJ_SYNPROXYS:
return do_list_obj(ctx, cmd, NFT_OBJECT_SYNPROXY);
+ case CMD_OBJ_FLOWTABLE:
+ return do_list_flowtable(ctx, cmd, table);
case CMD_OBJ_FLOWTABLES:
return do_list_flowtables(ctx, cmd);
default: