diff options
Diffstat (limited to 'src/flowtable.c')
-rw-r--r-- | src/flowtable.c | 215 |
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); |