From 0576274ad54a3aae2750e7a49bed1e0f406b61cc Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 30 Aug 2021 14:38:27 +0200 Subject: Introduce struct nftnl_str_array This data structure holds an array of allocated strings for use in nftnl_chain and nftnl_flowtable structs. For convenience, implement functions to clear, populate and iterate over contents. While at it, extend chain and flowtable tests to cover these attributes, too. Signed-off-by: Phil Sutter Reviewed-by: Pablo Neira Ayuso --- src/flowtable.c | 94 +++++++++------------------------------------------------ 1 file changed, 14 insertions(+), 80 deletions(-) (limited to 'src/flowtable.c') diff --git a/src/flowtable.c b/src/flowtable.c index 41a1456..2a8d374 100644 --- a/src/flowtable.c +++ b/src/flowtable.c @@ -26,8 +26,7 @@ struct nftnl_flowtable { uint32_t hooknum; int32_t prio; uint32_t size; - const char **dev_array; - uint32_t dev_array_len; + struct nftnl_str_array dev_array; uint32_t ft_flags; uint32_t use; uint32_t flags; @@ -43,18 +42,12 @@ struct nftnl_flowtable *nftnl_flowtable_alloc(void) EXPORT_SYMBOL(nftnl_flowtable_free); void nftnl_flowtable_free(const struct nftnl_flowtable *c) { - int i; - if (c->flags & (1 << NFTNL_FLOWTABLE_NAME)) xfree(c->name); if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE)) xfree(c->table); - if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) { - for (i = 0; i < c->dev_array_len; i++) - xfree(c->dev_array[i]); - - xfree(c->dev_array); - } + if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) + nftnl_str_array_clear((struct nftnl_str_array *)&c->dev_array); xfree(c); } @@ -67,8 +60,6 @@ bool nftnl_flowtable_is_set(const struct nftnl_flowtable *c, uint16_t attr) EXPORT_SYMBOL(nftnl_flowtable_unset); void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr) { - int i; - if (!(c->flags & (1 << attr))) return; @@ -87,9 +78,7 @@ void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr) case NFTNL_FLOWTABLE_HANDLE: break; case NFTNL_FLOWTABLE_DEVICES: - for (i = 0; i < c->dev_array_len; i++) - xfree(c->dev_array[i]); - xfree(c->dev_array); + nftnl_str_array_clear(&c->dev_array); break; default: return; @@ -111,9 +100,6 @@ EXPORT_SYMBOL(nftnl_flowtable_set_data); int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr, const void *data, uint32_t data_len) { - const char **dev_array; - int len = 0, i; - nftnl_assert_attr_exists(attr, NFTNL_FLOWTABLE_MAX); nftnl_assert_validate(data, nftnl_flowtable_validate, attr, data_len); @@ -135,24 +121,8 @@ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr, memcpy(&c->family, data, sizeof(c->family)); break; case NFTNL_FLOWTABLE_DEVICES: - dev_array = (const char **)data; - while (dev_array[len] != NULL) - len++; - - if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) { - for (i = 0; i < c->dev_array_len; i++) - xfree(c->dev_array[i]); - xfree(c->dev_array); - } - - c->dev_array = calloc(len + 1, sizeof(char *)); - if (!c->dev_array) + if (nftnl_str_array_set(&c->dev_array, data) < 0) return -1; - - for (i = 0; i < len; i++) - c->dev_array[i] = strdup(dev_array[i]); - - c->dev_array_len = len; break; case NFTNL_FLOWTABLE_SIZE: memcpy(&c->size, data, sizeof(c->size)); @@ -230,7 +200,7 @@ const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c, return &c->family; case NFTNL_FLOWTABLE_DEVICES: *data_len = 0; - return &c->dev_array[0]; + return c->dev_array.array; case NFTNL_FLOWTABLE_SIZE: *data_len = sizeof(int32_t); return &c->size; @@ -325,12 +295,11 @@ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh, if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) { struct nlattr *nest_dev; + const char *dev; 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]); - } + nftnl_str_array_foreach(dev, &c->dev_array, i) + mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev); mnl_attr_nest_end(nlh, nest_dev); } @@ -402,43 +371,6 @@ static int nftnl_flowtable_parse_hook_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } -static int nftnl_flowtable_parse_devs(struct nlattr *nest, - struct nftnl_flowtable *c) -{ - const char **dev_array, **tmp; - int len = 0, size = 8; - struct nlattr *attr; - - dev_array = calloc(8, sizeof(char *)); - if (!dev_array) - return -1; - - 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) { - tmp = realloc(dev_array, size * 2 * sizeof(char *)); - if (!tmp) - goto err; - - size *= 2; - memset(&tmp[len], 0, (size - len) * sizeof(char *)); - dev_array = tmp; - } - } - - c->dev_array = dev_array; - c->dev_array_len = len; - - return 0; -err: - while (len--) - xfree(dev_array[len]); - xfree(dev_array); - return -1; -} - static int nftnl_flowtable_parse_hook(struct nlattr *attr, struct nftnl_flowtable *c) { struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1] = {}; @@ -456,7 +388,8 @@ static int nftnl_flowtable_parse_hook(struct nlattr *attr, struct nftnl_flowtabl c->flags |= (1 << NFTNL_FLOWTABLE_PRIO); } if (tb[NFTA_FLOWTABLE_HOOK_DEVS]) { - ret = nftnl_flowtable_parse_devs(tb[NFTA_FLOWTABLE_HOOK_DEVS], c); + ret = nftnl_parse_devs(&c->dev_array, + tb[NFTA_FLOWTABLE_HOOK_DEVS]); if (ret < 0) return -1; c->flags |= (1 << NFTNL_FLOWTABLE_DEVICES); @@ -587,6 +520,7 @@ static int nftnl_flowtable_snprintf_default(char *buf, size_t remain, const struct nftnl_flowtable *c) { int ret, offset = 0, i; + const char *dev; ret = snprintf(buf, remain, "flow table %s %s use %u size %u flags %x", c->table, c->name, c->use, c->size, c->ft_flags); @@ -602,9 +536,9 @@ static int nftnl_flowtable_snprintf_default(char *buf, size_t remain, ret = snprintf(buf + offset, remain, " dev { "); SNPRINTF_BUFFER_SIZE(ret, remain, offset); - for (i = 0; i < c->dev_array_len; i++) { + nftnl_str_array_foreach(dev, &c->dev_array, i) { ret = snprintf(buf + offset, remain, " %s ", - c->dev_array[i]); + dev); SNPRINTF_BUFFER_SIZE(ret, remain, offset); } ret = snprintf(buf + offset, remain, " } "); -- cgit v1.2.3