summaryrefslogtreecommitdiffstats
path: root/src/flowtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/flowtable.c')
-rw-r--r--src/flowtable.c215
1 files changed, 129 insertions, 86 deletions
diff --git a/src/flowtable.c b/src/flowtable.c
index 1f7ba30..41a1456 100644
--- a/src/flowtable.c
+++ b/src/flowtable.c
@@ -17,7 +17,6 @@
#include <linux/netfilter_arp.h>
#include <libnftnl/flowtable.h>
-#include <buffer.h>
struct nftnl_flowtable {
struct list_head head;
@@ -32,14 +31,16 @@ struct nftnl_flowtable {
uint32_t ft_flags;
uint32_t use;
uint32_t flags;
+ uint64_t handle;
};
+EXPORT_SYMBOL(nftnl_flowtable_alloc);
struct nftnl_flowtable *nftnl_flowtable_alloc(void)
{
return calloc(1, sizeof(struct nftnl_flowtable));
}
-EXPORT_SYMBOL(nftnl_flowtable_alloc);
+EXPORT_SYMBOL(nftnl_flowtable_free);
void nftnl_flowtable_free(const struct nftnl_flowtable *c)
{
int i;
@@ -56,14 +57,14 @@ void nftnl_flowtable_free(const struct nftnl_flowtable *c)
}
xfree(c);
}
-EXPORT_SYMBOL(nftnl_flowtable_free);
+EXPORT_SYMBOL(nftnl_flowtable_is_set);
bool nftnl_flowtable_is_set(const struct nftnl_flowtable *c, uint16_t attr)
{
return c->flags & (1 << attr);
}
-EXPORT_SYMBOL(nftnl_flowtable_is_set);
+EXPORT_SYMBOL(nftnl_flowtable_unset);
void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr)
{
int i;
@@ -83,6 +84,7 @@ void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr)
case NFTNL_FLOWTABLE_USE:
case NFTNL_FLOWTABLE_FAMILY:
case NFTNL_FLOWTABLE_FLAGS:
+ case NFTNL_FLOWTABLE_HANDLE:
break;
case NFTNL_FLOWTABLE_DEVICES:
for (i = 0; i < c->dev_array_len; i++)
@@ -95,15 +97,17 @@ void nftnl_flowtable_unset(struct nftnl_flowtable *c, uint16_t attr)
c->flags &= ~(1 << attr);
}
-EXPORT_SYMBOL(nftnl_flowtable_unset);
static uint32_t nftnl_flowtable_validate[NFTNL_FLOWTABLE_MAX + 1] = {
[NFTNL_FLOWTABLE_HOOKNUM] = sizeof(uint32_t),
[NFTNL_FLOWTABLE_PRIO] = sizeof(int32_t),
[NFTNL_FLOWTABLE_FAMILY] = sizeof(uint32_t),
+ [NFTNL_FLOWTABLE_SIZE] = sizeof(uint32_t),
[NFTNL_FLOWTABLE_FLAGS] = sizeof(uint32_t),
+ [NFTNL_FLOWTABLE_HANDLE] = sizeof(uint64_t),
};
+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)
{
@@ -115,20 +119,11 @@ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr,
switch(attr) {
case NFTNL_FLOWTABLE_NAME:
- if (c->flags & (1 << NFTNL_FLOWTABLE_NAME))
- xfree(c->name);
-
- c->name = strdup(data);
- if (!c->name)
- return -1;
- break;
+ return nftnl_set_str_attr(&c->name, &c->flags,
+ attr, data, data_len);
case NFTNL_FLOWTABLE_TABLE:
- if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE))
- xfree(c->table);
-
- c->table = strdup(data);
- if (!c->table)
- return -1;
+ return nftnl_set_str_attr(&c->table, &c->flags,
+ attr, data, data_len);
break;
case NFTNL_FLOWTABLE_HOOKNUM:
memcpy(&c->hooknum, data, sizeof(c->hooknum));
@@ -165,36 +160,52 @@ int nftnl_flowtable_set_data(struct nftnl_flowtable *c, uint16_t attr,
case NFTNL_FLOWTABLE_FLAGS:
memcpy(&c->ft_flags, data, sizeof(c->ft_flags));
break;
+ case NFTNL_FLOWTABLE_HANDLE:
+ memcpy(&c->handle, data, sizeof(c->handle));
+ break;
}
c->flags |= (1 << attr);
return 0;
}
-EXPORT_SYMBOL(nftnl_flowtable_set_data);
+void nftnl_flowtable_set(struct nftnl_flowtable *c, uint16_t attr, const void *data) __visible;
void nftnl_flowtable_set(struct nftnl_flowtable *c, uint16_t attr, const void *data)
{
nftnl_flowtable_set_data(c, attr, data, nftnl_flowtable_validate[attr]);
}
-EXPORT_SYMBOL(nftnl_flowtable_set);
+EXPORT_SYMBOL(nftnl_flowtable_set_u32);
void nftnl_flowtable_set_u32(struct nftnl_flowtable *c, uint16_t attr, uint32_t data)
{
nftnl_flowtable_set_data(c, attr, &data, sizeof(uint32_t));
}
-EXPORT_SYMBOL(nftnl_flowtable_set_u32);
+EXPORT_SYMBOL(nftnl_flowtable_set_s32);
void nftnl_flowtable_set_s32(struct nftnl_flowtable *c, uint16_t attr, int32_t data)
{
nftnl_flowtable_set_data(c, attr, &data, sizeof(int32_t));
}
-EXPORT_SYMBOL(nftnl_flowtable_set_s32);
+EXPORT_SYMBOL(nftnl_flowtable_set_str);
int nftnl_flowtable_set_str(struct nftnl_flowtable *c, uint16_t attr, const char *str)
{
return nftnl_flowtable_set_data(c, attr, str, strlen(str) + 1);
}
-EXPORT_SYMBOL(nftnl_flowtable_set_str);
+EXPORT_SYMBOL(nftnl_flowtable_set_u64);
+void nftnl_flowtable_set_u64(struct nftnl_flowtable *c, uint16_t attr, uint64_t data)
+{
+ nftnl_flowtable_set_data(c, attr, &data, sizeof(uint64_t));
+}
+
+EXPORT_SYMBOL(nftnl_flowtable_set_array);
+int nftnl_flowtable_set_array(struct nftnl_flowtable *c, uint16_t attr,
+ const char **data)
+{
+ return nftnl_flowtable_set_data(c, attr, data, 0);
+}
+
+EXPORT_SYMBOL(nftnl_flowtable_get_data);
const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c,
uint16_t attr, uint32_t *data_len)
{
@@ -218,6 +229,7 @@ const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c,
*data_len = sizeof(int32_t);
return &c->family;
case NFTNL_FLOWTABLE_DEVICES:
+ *data_len = 0;
return &c->dev_array[0];
case NFTNL_FLOWTABLE_SIZE:
*data_len = sizeof(int32_t);
@@ -225,24 +237,27 @@ const void *nftnl_flowtable_get_data(const struct nftnl_flowtable *c,
case NFTNL_FLOWTABLE_FLAGS:
*data_len = sizeof(int32_t);
return &c->ft_flags;
+ case NFTNL_FLOWTABLE_HANDLE:
+ *data_len = sizeof(uint64_t);
+ return &c->handle;
}
return NULL;
}
-EXPORT_SYMBOL(nftnl_flowtable_get_data);
+EXPORT_SYMBOL(nftnl_flowtable_get);
const void *nftnl_flowtable_get(const struct nftnl_flowtable *c, uint16_t attr)
{
uint32_t data_len;
return nftnl_flowtable_get_data(c, attr, &data_len);
}
-EXPORT_SYMBOL(nftnl_flowtable_get);
+EXPORT_SYMBOL(nftnl_flowtable_get_str);
const char *nftnl_flowtable_get_str(const struct nftnl_flowtable *c, uint16_t attr)
{
return nftnl_flowtable_get(c, attr);
}
-EXPORT_SYMBOL(nftnl_flowtable_get_str);
+EXPORT_SYMBOL(nftnl_flowtable_get_u32);
uint32_t nftnl_flowtable_get_u32(const struct nftnl_flowtable *c, uint16_t attr)
{
uint32_t data_len = 0;
@@ -252,8 +267,19 @@ uint32_t nftnl_flowtable_get_u32(const struct nftnl_flowtable *c, uint16_t attr)
return val ? *val : 0;
}
-EXPORT_SYMBOL(nftnl_flowtable_get_u32);
+EXPORT_SYMBOL(nftnl_flowtable_get_u64);
+uint64_t nftnl_flowtable_get_u64(const struct nftnl_flowtable *c, uint16_t attr)
+{
+ uint32_t data_len = 0;
+ const uint64_t *val = nftnl_flowtable_get_data(c, attr, &data_len);
+
+ nftnl_assert(val, attr, data_len == sizeof(uint64_t));
+
+ return val ? *val : 0;
+}
+
+EXPORT_SYMBOL(nftnl_flowtable_get_s32);
int32_t nftnl_flowtable_get_s32(const struct nftnl_flowtable *c, uint16_t attr)
{
uint32_t data_len = 0;
@@ -263,44 +289,61 @@ int32_t nftnl_flowtable_get_s32(const struct nftnl_flowtable *c, uint16_t attr)
return val ? *val : 0;
}
-EXPORT_SYMBOL(nftnl_flowtable_get_s32);
+EXPORT_SYMBOL(nftnl_flowtable_get_array);
+const char *const *nftnl_flowtable_get_array(const struct nftnl_flowtable *c, uint16_t attr)
+{
+ uint32_t data_len;
+ const char * const *val = nftnl_flowtable_get_data(c, attr, &data_len);
+
+ nftnl_assert(val, attr, attr == NFTNL_FLOWTABLE_DEVICES);
+
+ return val;
+}
+
+EXPORT_SYMBOL(nftnl_flowtable_nlmsg_build_payload);
void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh,
const struct nftnl_flowtable *c)
{
+ struct nlattr *nest = NULL;
int i;
if (c->flags & (1 << NFTNL_FLOWTABLE_TABLE))
mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_TABLE, c->table);
if (c->flags & (1 << NFTNL_FLOWTABLE_NAME))
mnl_attr_put_strz(nlh, NFTA_FLOWTABLE_NAME, c->name);
- if ((c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM)) &&
- (c->flags & (1 << NFTNL_FLOWTABLE_PRIO))) {
- struct nlattr *nest;
+ if (c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM) ||
+ c->flags & (1 << NFTNL_FLOWTABLE_PRIO) ||
+ c->flags & (1 << NFTNL_FLOWTABLE_DEVICES))
nest = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK);
+
+ if (c->flags & (1 << NFTNL_FLOWTABLE_HOOKNUM))
mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_HOOK_NUM, htonl(c->hooknum));
+ if (c->flags & (1 << NFTNL_FLOWTABLE_PRIO))
mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(c->prio));
- if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) {
- struct nlattr *nest_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]);
- mnl_attr_nest_end(nlh, nest_dev);
+ if (c->flags & (1 << NFTNL_FLOWTABLE_DEVICES)) {
+ struct nlattr *nest_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]);
}
- mnl_attr_nest_end(nlh, nest);
+ mnl_attr_nest_end(nlh, nest_dev);
}
+
+ if (nest)
+ mnl_attr_nest_end(nlh, nest);
+
if (c->flags & (1 << NFTNL_FLOWTABLE_FLAGS))
mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_FLAGS, htonl(c->ft_flags));
if (c->flags & (1 << NFTNL_FLOWTABLE_USE))
mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_USE, htonl(c->use));
- if (c->flags & (1 << NFTNL_FLOWTABLE_SIZE))
- mnl_attr_put_u32(nlh, NFTA_FLOWTABLE_SIZE, htonl(c->size));
+ if (c->flags & (1 << NFTNL_FLOWTABLE_HANDLE))
+ mnl_attr_put_u64(nlh, NFTA_FLOWTABLE_HANDLE, htobe64(c->handle));
}
-EXPORT_SYMBOL(nftnl_flowtable_nlmsg_build_payload);
static int nftnl_flowtable_parse_attr_cb(const struct nlattr *attr, void *data)
{
@@ -325,6 +368,10 @@ static int nftnl_flowtable_parse_attr_cb(const struct nlattr *attr, void *data)
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
+ case NFTA_FLOWTABLE_HANDLE:
+ if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
+ abi_breakage();
+ break;
}
tb[type] = attr;
@@ -358,34 +405,37 @@ static int nftnl_flowtable_parse_hook_cb(const struct nlattr *attr, void *data)
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;
- char *dev_array[8];
- int len = 0, i;
+
+ 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 >= 8)
- break;
+ 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;
+ }
}
- if (!len)
- return -1;
-
- c->dev_array = calloc(len + 1, sizeof(char *));
- if (!c->dev_array)
- goto err;
-
+ c->dev_array = dev_array;
c->dev_array_len = len;
- for (i = 0; i < len; i++)
- c->dev_array[i] = dev_array[i];
-
return 0;
err:
while (len--)
xfree(dev_array[len]);
+ xfree(dev_array);
return -1;
}
@@ -415,6 +465,7 @@ static int nftnl_flowtable_parse_hook(struct nlattr *attr, struct nftnl_flowtabl
return 0;
}
+EXPORT_SYMBOL(nftnl_flowtable_nlmsg_parse);
int nftnl_flowtable_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_flowtable *c)
{
struct nlattr *tb[NFTA_FLOWTABLE_MAX + 1] = {};
@@ -453,9 +504,9 @@ int nftnl_flowtable_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_flowtab
c->use = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_USE]));
c->flags |= (1 << NFTNL_FLOWTABLE_USE);
}
- if (tb[NFTA_FLOWTABLE_SIZE]) {
- c->size = ntohl(mnl_attr_get_u32(tb[NFTA_FLOWTABLE_SIZE]));
- c->flags |= (1 << NFTNL_FLOWTABLE_SIZE);
+ if (tb[NFTA_FLOWTABLE_HANDLE]) {
+ c->handle = be64toh(mnl_attr_get_u64(tb[NFTA_FLOWTABLE_HANDLE]));
+ c->flags |= (1 << NFTNL_FLOWTABLE_HANDLE);
}
c->family = nfg->nfgen_family;
@@ -463,7 +514,6 @@ int nftnl_flowtable_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_flowtab
return ret;
}
-EXPORT_SYMBOL(nftnl_flowtable_nlmsg_parse);
static const char *nftnl_hooknum2str(int family, int hooknum)
{
@@ -516,14 +566,15 @@ static inline int nftnl_str2hooknum(int family, const char *hook)
return -1;
}
+EXPORT_SYMBOL(nftnl_flowtable_parse);
int nftnl_flowtable_parse(struct nftnl_flowtable *c, enum nftnl_parse_type type,
const char *data, struct nftnl_parse_err *err)
{
errno = EOPNOTSUPP;
return -1;
}
-EXPORT_SYMBOL(nftnl_flowtable_parse);
+EXPORT_SYMBOL(nftnl_flowtable_parse_file);
int nftnl_flowtable_parse_file(struct nftnl_flowtable *c,
enum nftnl_parse_type type,
FILE *fp, struct nftnl_parse_err *err)
@@ -531,12 +582,11 @@ int nftnl_flowtable_parse_file(struct nftnl_flowtable *c,
errno = EOPNOTSUPP;
return -1;
}
-EXPORT_SYMBOL(nftnl_flowtable_parse_file);
-static int nftnl_flowtable_snprintf_default(char *buf, size_t size,
+static int nftnl_flowtable_snprintf_default(char *buf, size_t remain,
const struct nftnl_flowtable *c)
{
- int ret, remain = size, offset = 0, i;
+ int ret, offset = 0, i;
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);
@@ -565,28 +615,22 @@ static int nftnl_flowtable_snprintf_default(char *buf, size_t size,
return offset;
}
-static int nftnl_flowtable_cmd_snprintf(char *buf, size_t size,
+static int nftnl_flowtable_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_flowtable *c,
uint32_t cmd, uint32_t type,
uint32_t flags)
{
- int ret, remain = size, offset = 0;
+ int ret, offset = 0;
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- ret = nftnl_flowtable_snprintf_default(buf + offset, remain, c);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- break;
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
+ ret = nftnl_flowtable_snprintf_default(buf + offset, remain, c);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
+EXPORT_SYMBOL(nftnl_flowtable_snprintf);
int nftnl_flowtable_snprintf(char *buf, size_t size, const struct nftnl_flowtable *c,
uint32_t type, uint32_t flags)
{
@@ -596,7 +640,6 @@ int nftnl_flowtable_snprintf(char *buf, size_t size, const struct nftnl_flowtabl
return nftnl_flowtable_cmd_snprintf(buf, size, c, nftnl_flag2cmd(flags),
type, flags);
}
-EXPORT_SYMBOL(nftnl_flowtable_snprintf);
static int nftnl_flowtable_do_snprintf(char *buf, size_t size, const void *c,
uint32_t cmd, uint32_t type, uint32_t flags)
@@ -604,18 +647,19 @@ static int nftnl_flowtable_do_snprintf(char *buf, size_t size, const void *c,
return nftnl_flowtable_snprintf(buf, size, c, type, flags);
}
+EXPORT_SYMBOL(nftnl_flowtable_fprintf);
int nftnl_flowtable_fprintf(FILE *fp, const struct nftnl_flowtable *c,
uint32_t type, uint32_t flags)
{
return nftnl_fprintf(fp, c, NFTNL_CMD_UNSPEC, type, flags,
nftnl_flowtable_do_snprintf);
}
-EXPORT_SYMBOL(nftnl_flowtable_fprintf);
struct nftnl_flowtable_list {
struct list_head list;
};
+EXPORT_SYMBOL(nftnl_flowtable_list_alloc);
struct nftnl_flowtable_list *nftnl_flowtable_list_alloc(void)
{
struct nftnl_flowtable_list *list;
@@ -628,8 +672,8 @@ struct nftnl_flowtable_list *nftnl_flowtable_list_alloc(void)
return list;
}
-EXPORT_SYMBOL(nftnl_flowtable_list_alloc);
+EXPORT_SYMBOL(nftnl_flowtable_list_free);
void nftnl_flowtable_list_free(struct nftnl_flowtable_list *list)
{
struct nftnl_flowtable *s, *tmp;
@@ -640,34 +684,34 @@ void nftnl_flowtable_list_free(struct nftnl_flowtable_list *list)
}
xfree(list);
}
-EXPORT_SYMBOL(nftnl_flowtable_list_free);
+EXPORT_SYMBOL(nftnl_flowtable_list_is_empty);
int nftnl_flowtable_list_is_empty(const struct nftnl_flowtable_list *list)
{
return list_empty(&list->list);
}
-EXPORT_SYMBOL(nftnl_flowtable_list_is_empty);
+EXPORT_SYMBOL(nftnl_flowtable_list_add);
void nftnl_flowtable_list_add(struct nftnl_flowtable *s,
struct nftnl_flowtable_list *list)
{
list_add(&s->head, &list->list);
}
-EXPORT_SYMBOL(nftnl_flowtable_list_add);
+EXPORT_SYMBOL(nftnl_flowtable_list_add_tail);
void nftnl_flowtable_list_add_tail(struct nftnl_flowtable *s,
struct nftnl_flowtable_list *list)
{
list_add_tail(&s->head, &list->list);
}
-EXPORT_SYMBOL(nftnl_flowtable_list_add_tail);
+EXPORT_SYMBOL(nftnl_flowtable_list_del);
void nftnl_flowtable_list_del(struct nftnl_flowtable *s)
{
list_del(&s->head);
}
-EXPORT_SYMBOL(nftnl_flowtable_list_del);
+EXPORT_SYMBOL(nftnl_flowtable_list_foreach);
int nftnl_flowtable_list_foreach(struct nftnl_flowtable_list *flowtable_list,
int (*cb)(struct nftnl_flowtable *t, void *data), void *data)
{
@@ -681,4 +725,3 @@ int nftnl_flowtable_list_foreach(struct nftnl_flowtable_list *flowtable_list,
}
return 0;
}
-EXPORT_SYMBOL(nftnl_flowtable_list_foreach);