Support simple (suffix) wildcards in NFTNL_CHAIN_DEV(ICES) and NFTA_FLOWTABLE_HOOK_DEVS identified by non-NUL-terminated strings. Add helpers converting to and from the human-readable asterisk-suffix notation. Signed-off-by: Phil Sutter <phil@xxxxxx> --- include/utils.h | 4 ++++ src/chain.c | 16 ++++++++++------ src/flowtable.c | 10 ++++++---- src/utils.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/include/utils.h b/include/utils.h index 247d99d19dd7f..c8e890eae2ffd 100644 --- a/include/utils.h +++ b/include/utils.h @@ -6,6 +6,7 @@ #include <stdint.h> #include <string.h> #include <stdlib.h> +#include <libmnl/libmnl.h> #include <libnftnl/common.h> #include "config.h" @@ -83,4 +84,7 @@ int nftnl_fprintf(FILE *fpconst, const void *obj, uint32_t cmd, uint32_t type, int nftnl_set_str_attr(const char **dptr, uint32_t *flags, uint16_t attr, const void *data, uint32_t data_len); +void mnl_attr_put_ifname(struct nlmsghdr *nlh, int attr, const char *ifname); +const char *mnl_attr_get_ifname(struct nlattr *attr); + #endif diff --git a/src/chain.c b/src/chain.c index 0b68939fe21a7..830e09fcfbbb1 100644 --- a/src/chain.c +++ b/src/chain.c @@ -490,14 +490,14 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio)); if (c->flags & (1 << NFTNL_CHAIN_DEV)) - mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev); + mnl_attr_put_ifname(nlh, NFTA_HOOK_DEV, c->dev); else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) { struct nlattr *nest_dev; nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS); for (i = 0; i < c->dev_array_len; i++) - mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, - c->dev_array[i]); + mnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, + c->dev_array[i]); mnl_attr_nest_end(nlh, nest_dev); } @@ -677,8 +677,10 @@ static int nftnl_chain_parse_devs(struct nlattr *nest, struct nftnl_chain *c) mnl_attr_for_each_nested(attr, nest) { if (mnl_attr_get_type(attr) != NFTA_DEVICE_NAME) goto err; - dev_array[len++] = strdup(mnl_attr_get_str(attr)); - if (len >= size) { + dev_array[len] = strdup(mnl_attr_get_ifname(attr)); + if (!dev_array[len]) + goto err; + if (++len >= size) { tmp = realloc(dev_array, size * 2 * sizeof(char *)); if (!tmp) goto err; @@ -717,7 +719,9 @@ static int nftnl_chain_parse_hook(struct nlattr *attr, struct nftnl_chain *c) c->flags |= (1 << NFTNL_CHAIN_PRIO); } if (tb[NFTA_HOOK_DEV]) { - c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV])); + if (c->flags & (1 << NFTNL_CHAIN_DEV)) + xfree(c->dev); + c->dev = strdup(mnl_attr_get_ifname(tb[NFTA_HOOK_DEV])); if (!c->dev) return -1; c->flags |= (1 << NFTNL_CHAIN_DEV); diff --git a/src/flowtable.c b/src/flowtable.c index 41a1456bb19b2..74cffc812996c 100644 --- a/src/flowtable.c +++ b/src/flowtable.c @@ -328,8 +328,8 @@ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh, nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS); for (i = 0; i < c->dev_array_len; i++) { - mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, - c->dev_array[i]); + mnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, + c->dev_array[i]); } mnl_attr_nest_end(nlh, nest_dev); } @@ -416,8 +416,10 @@ static int nftnl_flowtable_parse_devs(struct nlattr *nest, mnl_attr_for_each_nested(attr, nest) { if (mnl_attr_get_type(attr) != NFTA_DEVICE_NAME) goto err; - dev_array[len++] = strdup(mnl_attr_get_str(attr)); - if (len >= size) { + dev_array[len] = strdup(mnl_attr_get_ifname(attr)); + if (!dev_array[len]) + goto err; + if (++len >= size) { tmp = realloc(dev_array, size * 2 * sizeof(char *)); if (!tmp) goto err; diff --git a/src/utils.c b/src/utils.c index 2f1ffd6227583..df00ce04b32ea 100644 --- a/src/utils.c +++ b/src/utils.c @@ -17,8 +17,11 @@ #include <errno.h> #include <inttypes.h> +#include <libmnl/libmnl.h> + #include <libnftnl/common.h> +#include <linux/if.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> @@ -150,3 +153,30 @@ int nftnl_set_str_attr(const char **dptr, uint32_t *flags, *flags |= (1 << attr); return 0; } + +void mnl_attr_put_ifname(struct nlmsghdr *nlh, int attr, const char *ifname) +{ + int len = strlen(ifname) + 1; + + if (ifname[len - 2] == '*') + len -= 2; + + mnl_attr_put(nlh, attr, len, ifname); +} + +const char *mnl_attr_get_ifname(struct nlattr *attr) +{ + size_t slen = mnl_attr_get_payload_len(attr); + const char *dev = mnl_attr_get_str(attr); + static char buf[IFNAMSIZ]; + + if (dev[slen - 1] == '\0') + return dev; + + if (slen > IFNAMSIZ - 2) + slen = IFNAMSIZ - 2; + + memcpy(buf, dev, slen); + memcpy(buf + slen, "*\0", 2); + return buf; +} -- 2.43.0