From db0697ce7f6020b525cee072e7c0c85512daabda Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 4 Dec 2017 13:28:25 +0100 Subject: src: support for flowtable listing This patch allows you to dump existing flowtable. # nft list ruleset table ip x { flowtable x { hook ingress priority 10 devices = { eth0, tap0 } } } You can also list existing flowtables via: # nft list flowtables table ip x { flowtable x { hook ingress priority 10 devices = { eth0, tap0 } } } You need a Linux kernel >= 4.16-rc to test this new feature. Signed-off-by: Pablo Neira Ayuso --- src/netlink.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'src/netlink.c') diff --git a/src/netlink.c b/src/netlink.c index 403f93ca..9fadccd0 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -1542,6 +1543,70 @@ int netlink_reset_objs(struct netlink_ctx *ctx, const struct handle *h, return err; } +static struct flowtable * +netlink_delinearize_flowtable(struct netlink_ctx *ctx, + struct nftnl_flowtable *nlo) +{ + struct flowtable *flowtable; + const char **dev_array; + int len = 0, i; + + flowtable = flowtable_alloc(&netlink_location); + flowtable->handle.family = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY); + flowtable->handle.table = + xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE)); + flowtable->handle.flowtable = + xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME)); + dev_array = nftnl_flowtable_get_array(nlo, NFTNL_FLOWTABLE_DEVICES); + while (dev_array[len] != '\0') + len++; + + flowtable->dev_array = calloc(1, len * sizeof(char *)); + for (i = 0; i < len; i++) + flowtable->dev_array[i] = xstrdup(dev_array[i]); + + flowtable->dev_array_len = len; + + flowtable->priority = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_PRIO); + flowtable->hooknum = + nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_HOOKNUM); + + return flowtable; +} + +static int list_flowtable_cb(struct nftnl_flowtable *nls, void *arg) +{ + struct netlink_ctx *ctx = arg; + struct flowtable *flowtable; + + flowtable = netlink_delinearize_flowtable(ctx, nls); + if (flowtable == NULL) + return -1; + list_add_tail(&flowtable->list, &ctx->list); + return 0; +} + +int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h, + const struct location *loc) +{ + struct nftnl_flowtable_list *flowtable_cache; + int err; + + flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family, h->table); + if (flowtable_cache == NULL) { + if (errno == EINTR) + return -1; + + return 0; + } + + err = nftnl_flowtable_list_foreach(flowtable_cache, list_flowtable_cb, ctx); + nftnl_flowtable_list_free(flowtable_cache); + return err; +} + int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list) { return mnl_batch_talk(ctx, err_list); -- cgit v1.2.3