summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/batch.c5
-rw-r--r--src/chain.c153
-rw-r--r--src/common.c8
-rw-r--r--src/expr.c24
-rw-r--r--src/expr/bitwise.c61
-rw-r--r--src/expr/byteorder.c35
-rw-r--r--src/expr/cmp.c39
-rw-r--r--src/expr/connlimit.c30
-rw-r--r--src/expr/counter.c30
-rw-r--r--src/expr/ct.c35
-rw-r--r--src/expr/data_reg.c60
-rw-r--r--src/expr/dup.c35
-rw-r--r--src/expr/dynset.c156
-rw-r--r--src/expr/exthdr.c42
-rw-r--r--src/expr/fib.c32
-rw-r--r--src/expr/flow_offload.c31
-rw-r--r--src/expr/fwd.c32
-rw-r--r--src/expr/hash.c34
-rw-r--r--src/expr/immediate.c61
-rw-r--r--src/expr/inner.c220
-rw-r--r--src/expr/last.c142
-rw-r--r--src/expr/limit.c33
-rw-r--r--src/expr/log.c38
-rw-r--r--src/expr/lookup.c36
-rw-r--r--src/expr/masq.c49
-rw-r--r--src/expr/match.c26
-rw-r--r--src/expr/meta.c33
-rw-r--r--src/expr/nat.c56
-rw-r--r--src/expr/numgen.c31
-rw-r--r--src/expr/objref.c38
-rw-r--r--src/expr/osf.c31
-rw-r--r--src/expr/payload.c70
-rw-r--r--src/expr/queue.c46
-rw-r--r--src/expr/quota.c31
-rw-r--r--src/expr/range.c44
-rw-r--r--src/expr/redir.c39
-rw-r--r--src/expr/reject.c30
-rw-r--r--src/expr/rt.c29
-rw-r--r--src/expr/socket.c62
-rw-r--r--src/expr/synproxy.c31
-rw-r--r--src/expr/target.c26
-rw-r--r--src/expr/tproxy.c30
-rw-r--r--src/expr/tunnel.c42
-rw-r--r--src/expr/xfrm.c60
-rw-r--r--src/expr_ops.c4
-rw-r--r--src/flowtable.c71
-rw-r--r--src/gen.c14
-rw-r--r--src/libnftnl.map29
-rw-r--r--src/obj/counter.c24
-rw-r--r--src/obj/ct_expect.c41
-rw-r--r--src/obj/ct_helper.c24
-rw-r--r--src/obj/ct_timeout.c48
-rw-r--r--src/obj/limit.c25
-rw-r--r--src/obj/quota.c25
-rw-r--r--src/obj/secmark.c25
-rw-r--r--src/obj/synproxy.c24
-rw-r--r--src/obj/tunnel.c23
-rw-r--r--src/object.c96
-rw-r--r--src/rule.c62
-rw-r--r--src/ruleset.c200
-rw-r--r--src/set.c152
-rw-r--r--src/set_elem.c207
-rw-r--r--src/table.c63
-rw-r--r--src/udata.c8
-rw-r--r--src/utils.c194
66 files changed, 1892 insertions, 1645 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 90b1967..3cd259c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,11 +34,13 @@ libnftnl_la_SOURCES = utils.c \
expr/flow_offload.c \
expr/fib.c \
expr/fwd.c \
+ expr/last.c \
expr/limit.c \
expr/log.c \
expr/lookup.c \
expr/dynset.c \
expr/immediate.c \
+ expr/inner.c \
expr/match.c \
expr/meta.c \
expr/numgen.c \
diff --git a/src/batch.c b/src/batch.c
index ca8f922..8a9c6f9 100644
--- a/src/batch.c
+++ b/src/batch.c
@@ -2,8 +2,9 @@
* Copyright (c) 2013-2015 Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*/
#include "internal.h"
diff --git a/src/chain.c b/src/chain.c
index b4066e4..dcfcd04 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -43,11 +43,18 @@ struct nftnl_chain {
uint32_t policy;
uint32_t hooknum;
int32_t prio;
+ uint32_t chain_flags;
uint32_t use;
uint64_t packets;
uint64_t bytes;
uint64_t handle;
uint32_t flags;
+ uint32_t chain_id;
+
+ struct {
+ void *data;
+ uint32_t len;
+ } user;
struct list_head rule_list;
};
@@ -123,6 +130,8 @@ void nftnl_chain_free(const struct nftnl_chain *c)
xfree(c->type);
if (c->flags & (1 << NFTNL_CHAIN_DEV))
xfree(c->dev);
+ if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
+ xfree(c->user.data);
if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
for (i = 0; i < c->dev_array_len; i++)
xfree(c->dev_array[i]);
@@ -165,6 +174,8 @@ void nftnl_chain_unset(struct nftnl_chain *c, uint16_t attr)
case NFTNL_CHAIN_PACKETS:
case NFTNL_CHAIN_HANDLE:
case NFTNL_CHAIN_FAMILY:
+ case NFTNL_CHAIN_FLAGS:
+ case NFTNL_CHAIN_ID:
break;
case NFTNL_CHAIN_DEV:
xfree(c->dev);
@@ -189,6 +200,8 @@ static uint32_t nftnl_chain_validate[NFTNL_CHAIN_MAX + 1] = {
[NFTNL_CHAIN_PACKETS] = sizeof(uint64_t),
[NFTNL_CHAIN_HANDLE] = sizeof(uint64_t),
[NFTNL_CHAIN_FAMILY] = sizeof(uint32_t),
+ [NFTNL_CHAIN_FLAGS] = sizeof(uint32_t),
+ [NFTNL_CHAIN_ID] = sizeof(uint32_t),
};
EXPORT_SYMBOL(nftnl_chain_set_data);
@@ -278,6 +291,22 @@ int nftnl_chain_set_data(struct nftnl_chain *c, uint16_t attr,
c->dev_array_len = len;
break;
+ case NFTNL_CHAIN_FLAGS:
+ memcpy(&c->chain_flags, data, sizeof(c->chain_flags));
+ break;
+ case NFTNL_CHAIN_ID:
+ memcpy(&c->chain_id, data, sizeof(c->chain_id));
+ break;
+ case NFTNL_CHAIN_USERDATA:
+ if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
+ xfree(c->user.data);
+
+ c->user.data = malloc(data_len);
+ if (!c->user.data)
+ return -1;
+ memcpy(c->user.data, data, data_len);
+ c->user.len = data_len;
+ break;
}
c->flags |= (1 << attr);
return 0;
@@ -319,6 +348,13 @@ int nftnl_chain_set_str(struct nftnl_chain *c, uint16_t attr, const char *str)
return nftnl_chain_set_data(c, attr, str, strlen(str) + 1);
}
+EXPORT_SYMBOL(nftnl_chain_set_array);
+int nftnl_chain_set_array(struct nftnl_chain *c, uint16_t attr,
+ const char **data)
+{
+ return nftnl_chain_set_data(c, attr, data, 0);
+}
+
EXPORT_SYMBOL(nftnl_chain_get_data);
const void *nftnl_chain_get_data(const struct nftnl_chain *c, uint16_t attr,
uint32_t *data_len)
@@ -364,7 +400,17 @@ const void *nftnl_chain_get_data(const struct nftnl_chain *c, uint16_t attr,
*data_len = strlen(c->dev) + 1;
return c->dev;
case NFTNL_CHAIN_DEVICES:
+ *data_len = 0;
return &c->dev_array[0];
+ case NFTNL_CHAIN_FLAGS:
+ *data_len = sizeof(uint32_t);
+ return &c->chain_flags;
+ case NFTNL_CHAIN_ID:
+ *data_len = sizeof(uint32_t);
+ return &c->chain_id;
+ case NFTNL_CHAIN_USERDATA:
+ *data_len = c->user.len;
+ return c->user.data;
}
return NULL;
}
@@ -426,43 +472,63 @@ uint8_t nftnl_chain_get_u8(const struct nftnl_chain *c, uint16_t attr)
return val ? *val : 0;
}
+EXPORT_SYMBOL(nftnl_chain_get_array);
+const char *const *nftnl_chain_get_array(const struct nftnl_chain *c, uint16_t attr)
+{
+ uint32_t data_len;
+ const char * const *val = nftnl_chain_get_data(c, attr, &data_len);
+
+ nftnl_assert(val, attr, attr == NFTNL_CHAIN_DEVICES);
+
+ return val;
+}
+
EXPORT_SYMBOL(nftnl_chain_nlmsg_build_payload);
void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_chain *c)
{
+ struct nlattr *nest = NULL;
int i;
if (c->flags & (1 << NFTNL_CHAIN_TABLE))
mnl_attr_put_strz(nlh, NFTA_CHAIN_TABLE, c->table);
if (c->flags & (1 << NFTNL_CHAIN_NAME))
mnl_attr_put_strz(nlh, NFTA_CHAIN_NAME, c->name);
- if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) &&
- (c->flags & (1 << NFTNL_CHAIN_PRIO))) {
- struct nlattr *nest;
+ if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) ||
+ (c->flags & (1 << NFTNL_CHAIN_PRIO)) ||
+ (c->flags & (1 << NFTNL_CHAIN_DEV)) ||
+ (c->flags & (1 << NFTNL_CHAIN_DEVICES)))
nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_HOOK);
+
+ if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)))
mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(c->hooknum));
+ if ((c->flags & (1 << NFTNL_CHAIN_PRIO)))
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);
- 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_nest_end(nlh, nest_dev);
- }
- mnl_attr_nest_end(nlh, nest);
+ if (c->flags & (1 << NFTNL_CHAIN_DEV))
+ mnl_attr_put_strz(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_nest_end(nlh, nest_dev);
}
+
+ if ((c->flags & (1 << NFTNL_CHAIN_HOOKNUM)) ||
+ (c->flags & (1 << NFTNL_CHAIN_PRIO)) ||
+ (c->flags & (1 << NFTNL_CHAIN_DEV)) ||
+ (c->flags & (1 << NFTNL_CHAIN_DEVICES)))
+ mnl_attr_nest_end(nlh, nest);
+
if (c->flags & (1 << NFTNL_CHAIN_POLICY))
mnl_attr_put_u32(nlh, NFTA_CHAIN_POLICY, htonl(c->policy));
if (c->flags & (1 << NFTNL_CHAIN_USE))
mnl_attr_put_u32(nlh, NFTA_CHAIN_USE, htonl(c->use));
if ((c->flags & (1 << NFTNL_CHAIN_PACKETS)) &&
(c->flags & (1 << NFTNL_CHAIN_BYTES))) {
- struct nlattr *nest;
-
nest = mnl_attr_nest_start(nlh, NFTA_CHAIN_COUNTERS);
mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, be64toh(c->packets));
mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, be64toh(c->bytes));
@@ -472,6 +538,12 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch
mnl_attr_put_u64(nlh, NFTA_CHAIN_HANDLE, be64toh(c->handle));
if (c->flags & (1 << NFTNL_CHAIN_TYPE))
mnl_attr_put_strz(nlh, NFTA_CHAIN_TYPE, c->type);
+ if (c->flags & (1 << NFTNL_CHAIN_FLAGS))
+ mnl_attr_put_u32(nlh, NFTA_CHAIN_FLAGS, htonl(c->chain_flags));
+ if (c->flags & (1 << NFTNL_CHAIN_ID))
+ mnl_attr_put_u32(nlh, NFTA_CHAIN_ID, htonl(c->chain_id));
+ if (c->flags & (1 << NFTNL_CHAIN_USERDATA))
+ mnl_attr_put(nlh, NFTA_CHAIN_USERDATA, c->user.len, c->user.data);
}
EXPORT_SYMBOL(nftnl_chain_rule_add);
@@ -526,6 +598,8 @@ static int nftnl_chain_parse_attr_cb(const struct nlattr *attr, void *data)
break;
case NFTA_CHAIN_POLICY:
case NFTA_CHAIN_USE:
+ case NFTA_CHAIN_FLAGS:
+ case NFTA_CHAIN_ID:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -533,6 +607,10 @@ static int nftnl_chain_parse_attr_cb(const struct nlattr *attr, void *data)
if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
abi_breakage();
break;
+ case NFTA_CHAIN_USERDATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+ abi_breakage();
+ break;
}
tb[type] = attr;
@@ -726,6 +804,19 @@ int nftnl_chain_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_chain *c)
return -1;
c->flags |= (1 << NFTNL_CHAIN_TYPE);
}
+ if (tb[NFTA_CHAIN_FLAGS]) {
+ c->chain_flags = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_FLAGS]));
+ c->flags |= (1 << NFTNL_CHAIN_FLAGS);
+ }
+ if (tb[NFTA_CHAIN_ID]) {
+ c->chain_id = ntohl(mnl_attr_get_u32(tb[NFTA_CHAIN_ID]));
+ c->flags |= (1 << NFTNL_CHAIN_ID);
+ }
+ if (tb[NFTA_CHAIN_USERDATA]) {
+ nftnl_chain_set_data(c, NFTNL_CHAIN_USERDATA,
+ mnl_attr_get_payload(tb[NFTA_CHAIN_USERDATA]),
+ mnl_attr_get_payload_len(tb[NFTA_CHAIN_USERDATA]));
+ }
c->family = nfg->nfgen_family;
c->flags |= (1 << NFTNL_CHAIN_FAMILY);
@@ -744,10 +835,10 @@ static inline int nftnl_str2hooknum(int family, const char *hook)
return -1;
}
-static int nftnl_chain_snprintf_default(char *buf, size_t size,
+static int nftnl_chain_snprintf_default(char *buf, size_t remain,
const struct nftnl_chain *c)
{
- int ret, remain = size, offset = 0, i;
+ int ret, offset = 0, i;
ret = snprintf(buf, remain, "%s %s %s use %u",
nftnl_family2str(c->family), c->table, c->name, c->use);
@@ -787,28 +878,32 @@ static int nftnl_chain_snprintf_default(char *buf, size_t size,
ret = snprintf(buf + offset, remain, " } ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
+ if (c->flags & (1 << NFTNL_CHAIN_FLAGS)) {
+ ret = snprintf(buf + offset, remain, " flags %x",
+ c->chain_flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+ if (c->flags & (1 << NFTNL_CHAIN_ID)) {
+ ret = snprintf(buf + offset, remain, " id %x",
+ c->chain_id);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
}
return offset;
}
-static int nftnl_chain_cmd_snprintf(char *buf, size_t size,
+static int nftnl_chain_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_chain *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_chain_snprintf_default(buf + offset, remain, c);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
+ ret = nftnl_chain_snprintf_default(buf + offset, remain, c);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/common.c b/src/common.c
index 2d83c12..ec84fa0 100644
--- a/src/common.c
+++ b/src/common.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <sys/socket.h>
#include <time.h>
+#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
@@ -37,7 +38,7 @@ static struct nlmsghdr *__nftnl_nlmsg_build_hdr(char *buf, uint16_t type,
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
nfh->nfgen_family = family;
nfh->version = NFNETLINK_V0;
- nfh->res_id = res_id;
+ nfh->res_id = htons(res_id);
return nlh;
}
@@ -126,9 +127,8 @@ int nftnl_batch_is_supported(void)
mnl_nlmsg_batch_next(b);
req_seq = seq;
- nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(b),
- NFT_MSG_NEWSET, AF_INET,
- NLM_F_ACK, seq++);
+ nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(b), NFT_MSG_NEWSET,
+ AF_INET, NLM_F_ACK, seq++);
mnl_nlmsg_batch_next(b);
nftnl_batch_end(mnl_nlmsg_batch_current(b), seq++);
diff --git a/src/expr.c b/src/expr.c
index 80c4c36..4e32189 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -42,6 +42,9 @@ struct nftnl_expr *nftnl_expr_alloc(const char *name)
expr->flags |= (1 << NFTNL_EXPR_NAME);
expr->ops = ops;
+ if (ops->init)
+ ops->init(expr);
+
return expr;
}
@@ -68,6 +71,16 @@ int nftnl_expr_set(struct nftnl_expr *expr, uint16_t type,
case NFTNL_EXPR_NAME: /* cannot be modified */
return 0;
default:
+ if (type < NFTNL_EXPR_BASE || type > expr->ops->nftnl_max_attr)
+ return -1;
+
+ if (!expr->ops->attr_policy)
+ return -1;
+
+ if (expr->ops->attr_policy[type].maxlen &&
+ expr->ops->attr_policy[type].maxlen < data_len)
+ return -1;
+
if (expr->ops->set(expr, type, data, data_len) < 0)
return -1;
}
@@ -203,6 +216,7 @@ const char *nftnl_expr_get_str(const struct nftnl_expr *expr, uint16_t type)
return (const char *)nftnl_expr_get(expr, type, &data_len);
}
+EXPORT_SYMBOL(nftnl_expr_build_payload);
void nftnl_expr_build_payload(struct nlmsghdr *nlh, struct nftnl_expr *expr)
{
struct nlattr *nest;
@@ -266,19 +280,19 @@ err1:
}
EXPORT_SYMBOL(nftnl_expr_snprintf);
-int nftnl_expr_snprintf(char *buf, size_t size, const struct nftnl_expr *expr,
+int nftnl_expr_snprintf(char *buf, size_t remain, const struct nftnl_expr *expr,
uint32_t type, uint32_t flags)
{
int ret;
- unsigned int offset = 0, remain = size;
+ unsigned int offset = 0;
- if (size)
+ if (remain)
buf[0] = '\0';
- if (!expr->ops->snprintf)
+ if (!expr->ops->output || type != NFTNL_OUTPUT_DEFAULT)
return 0;
- ret = expr->ops->snprintf(buf + offset, remain, type, flags, expr);
+ ret = expr->ops->output(buf + offset, remain, flags, expr);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index 9ea2f66..dab1690 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -51,19 +51,11 @@ nftnl_expr_bitwise_set(struct nftnl_expr *e, uint16_t type,
memcpy(&bitwise->len, data, sizeof(bitwise->len));
break;
case NFTNL_EXPR_BITWISE_MASK:
- memcpy(&bitwise->mask.val, data, data_len);
- bitwise->mask.len = data_len;
- break;
+ return nftnl_data_cpy(&bitwise->mask, data, data_len);
case NFTNL_EXPR_BITWISE_XOR:
- memcpy(&bitwise->xor.val, data, data_len);
- bitwise->xor.len = data_len;
- break;
+ return nftnl_data_cpy(&bitwise->xor, data, data_len);
case NFTNL_EXPR_BITWISE_DATA:
- memcpy(&bitwise->data.val, data, data_len);
- bitwise->data.len = data_len;
- break;
- default:
- return -1;
+ return nftnl_data_cpy(&bitwise->data, data, data_len);
}
return 0;
}
@@ -210,40 +202,40 @@ nftnl_expr_bitwise_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_bitwise_snprintf_bool(char *buf, size_t size,
+nftnl_expr_bitwise_snprintf_bool(char *buf, size_t remain,
const struct nftnl_expr_bitwise *bitwise)
{
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
- ret = snprintf(buf, remain, "reg %u = (reg=%u & ",
+ ret = snprintf(buf, remain, "reg %u = ( reg %u & ",
bitwise->dreg, bitwise->sreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->mask,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = snprintf(buf + offset, remain, ") ^ ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->xor,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
static int
-nftnl_expr_bitwise_snprintf_shift(char *buf, size_t size, const char *op,
+nftnl_expr_bitwise_snprintf_shift(char *buf, size_t remain, const char *op,
const struct nftnl_expr_bitwise *bitwise)
-{ int remain = size, offset = 0, ret;
+{ int offset = 0, ret;
ret = snprintf(buf, remain, "reg %u = ( reg %u %s ",
bitwise->dreg, bitwise->sreg, op);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &bitwise->data,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = snprintf(buf + offset, remain, ") ");
@@ -252,8 +244,9 @@ nftnl_expr_bitwise_snprintf_shift(char *buf, size_t size, const char *op,
return offset;
}
-static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_bitwise_snprintf(char *buf, size_t size,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_bitwise *bitwise = nftnl_expr_data(e);
int err = -1;
@@ -273,26 +266,24 @@ static int nftnl_expr_bitwise_snprintf_default(char *buf, size_t size,
return err;
}
-static int
-nftnl_expr_bitwise_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_bitwise_snprintf_default(buf, size, e);
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy bitwise_attr_policy[__NFTNL_EXPR_BITWISE_MAX] = {
+ [NFTNL_EXPR_BITWISE_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BITWISE_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BITWISE_LEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BITWISE_MASK] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+ [NFTNL_EXPR_BITWISE_XOR] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+ [NFTNL_EXPR_BITWISE_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BITWISE_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+};
struct expr_ops expr_ops_bitwise = {
.name = "bitwise",
.alloc_len = sizeof(struct nftnl_expr_bitwise),
- .max_attr = NFTA_BITWISE_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_BITWISE_MAX - 1,
+ .attr_policy = bitwise_attr_policy,
.set = nftnl_expr_bitwise_set,
.get = nftnl_expr_bitwise_get,
.parse = nftnl_expr_bitwise_parse,
.build = nftnl_expr_bitwise_build,
- .snprintf = nftnl_expr_bitwise_snprintf,
+ .output = nftnl_expr_bitwise_snprintf,
};
diff --git a/src/expr/byteorder.c b/src/expr/byteorder.c
index efdfa2b..d4e85a8 100644
--- a/src/expr/byteorder.c
+++ b/src/expr/byteorder.c
@@ -51,8 +51,6 @@ nftnl_expr_byteorder_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_BYTEORDER_SIZE:
memcpy(&byteorder->size, data, sizeof(byteorder->size));
break;
- default:
- return -1;
}
return 0;
}
@@ -197,11 +195,12 @@ static inline int nftnl_str2ntoh(const char *op)
}
}
-static int nftnl_expr_byteorder_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_byteorder_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
ret = snprintf(buf, remain, "reg %u = %s(reg %u, %u, %u) ",
byteorder->dreg, bo2str(byteorder->op),
@@ -211,28 +210,22 @@ static int nftnl_expr_byteorder_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_byteorder_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_byteorder_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy byteorder_attr_policy[__NFTNL_EXPR_BYTEORDER_MAX] = {
+ [NFTNL_EXPR_BYTEORDER_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BYTEORDER_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BYTEORDER_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BYTEORDER_LEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_BYTEORDER_SIZE] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_byteorder = {
.name = "byteorder",
.alloc_len = sizeof(struct nftnl_expr_byteorder),
- .max_attr = NFTA_BYTEORDER_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_BYTEORDER_MAX - 1,
+ .attr_policy = byteorder_attr_policy,
.set = nftnl_expr_byteorder_set,
.get = nftnl_expr_byteorder_get,
.parse = nftnl_expr_byteorder_parse,
.build = nftnl_expr_byteorder_build,
- .snprintf = nftnl_expr_byteorder_snprintf,
+ .output = nftnl_expr_byteorder_snprintf,
};
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index 86d7842..2937d7e 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -42,11 +42,7 @@ nftnl_expr_cmp_set(struct nftnl_expr *e, uint16_t type,
memcpy(&cmp->op, data, sizeof(cmp->op));
break;
case NFTNL_EXPR_CMP_DATA:
- memcpy(&cmp->data.val, data, data_len);
- cmp->data.len = data_len;
- break;
- default:
- return -1;
+ return nftnl_data_cpy(&cmp->data, data, data_len);
}
return 0;
}
@@ -176,45 +172,38 @@ static inline int nftnl_str2cmp(const char *op)
}
}
-static int nftnl_expr_cmp_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_cmp_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_cmp *cmp = nftnl_expr_data(e);
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
ret = snprintf(buf, remain, "%s reg %u ",
cmp2str(cmp->op), cmp->sreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &cmp->data,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
-static int
-nftnl_expr_cmp_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_cmp_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy cmp_attr_policy[__NFTNL_EXPR_CMP_MAX] = {
+ [NFTNL_EXPR_CMP_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_CMP_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_CMP_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN }
+};
struct expr_ops expr_ops_cmp = {
.name = "cmp",
.alloc_len = sizeof(struct nftnl_expr_cmp),
- .max_attr = NFTA_CMP_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_CMP_MAX - 1,
+ .attr_policy = cmp_attr_policy,
.set = nftnl_expr_cmp_set,
.get = nftnl_expr_cmp_get,
.parse = nftnl_expr_cmp_parse,
.build = nftnl_expr_cmp_build,
- .snprintf = nftnl_expr_cmp_snprintf,
+ .output = nftnl_expr_cmp_snprintf,
};
diff --git a/src/expr/connlimit.c b/src/expr/connlimit.c
index 53af93b..1c78c71 100644
--- a/src/expr/connlimit.c
+++ b/src/expr/connlimit.c
@@ -38,8 +38,6 @@ nftnl_expr_connlimit_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_CONNLIMIT_FLAGS:
memcpy(&connlimit->flags, data, sizeof(connlimit->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -117,8 +115,9 @@ nftnl_expr_connlimit_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_connlimit_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int nftnl_expr_connlimit_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_expr *e)
{
struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
@@ -126,28 +125,19 @@ static int nftnl_expr_connlimit_snprintf_default(char *buf, size_t len,
connlimit->count, connlimit->flags);
}
-static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_connlimit_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy connlimit_attr_policy[__NFTNL_EXPR_CONNLIMIT_MAX] = {
+ [NFTNL_EXPR_CONNLIMIT_COUNT] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_CONNLIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_connlimit = {
.name = "connlimit",
.alloc_len = sizeof(struct nftnl_expr_connlimit),
- .max_attr = NFTA_CONNLIMIT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_CONNLIMIT_MAX - 1,
+ .attr_policy = connlimit_attr_policy,
.set = nftnl_expr_connlimit_set,
.get = nftnl_expr_connlimit_get,
.parse = nftnl_expr_connlimit_parse,
.build = nftnl_expr_connlimit_build,
- .snprintf = nftnl_expr_connlimit_snprintf,
+ .output = nftnl_expr_connlimit_snprintf,
};
diff --git a/src/expr/counter.c b/src/expr/counter.c
index 89a602e..2c6f2a7 100644
--- a/src/expr/counter.c
+++ b/src/expr/counter.c
@@ -40,8 +40,6 @@ nftnl_expr_counter_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_CTR_PACKETS:
memcpy(&ctr->pkts, data, sizeof(ctr->pkts));
break;
- default:
- return -1;
}
return 0;
}
@@ -115,8 +113,9 @@ nftnl_expr_counter_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_counter_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int nftnl_expr_counter_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_expr *e)
{
struct nftnl_expr_counter *ctr = nftnl_expr_data(e);
@@ -124,28 +123,19 @@ static int nftnl_expr_counter_snprintf_default(char *buf, size_t len,
ctr->pkts, ctr->bytes);
}
-static int nftnl_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_counter_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy counter_attr_policy[__NFTNL_EXPR_CTR_MAX] = {
+ [NFTNL_EXPR_CTR_PACKETS] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_CTR_BYTES] = { .maxlen = sizeof(uint64_t) },
+};
struct expr_ops expr_ops_counter = {
.name = "counter",
.alloc_len = sizeof(struct nftnl_expr_counter),
- .max_attr = NFTA_COUNTER_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_CTR_MAX - 1,
+ .attr_policy = counter_attr_policy,
.set = nftnl_expr_counter_set,
.get = nftnl_expr_counter_get,
.parse = nftnl_expr_counter_parse,
.build = nftnl_expr_counter_build,
- .snprintf = nftnl_expr_counter_snprintf,
+ .output = nftnl_expr_counter_snprintf,
};
diff --git a/src/expr/ct.c b/src/expr/ct.c
index 124de9d..f7dd40d 100644
--- a/src/expr/ct.c
+++ b/src/expr/ct.c
@@ -50,8 +50,6 @@ nftnl_expr_ct_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_CT_SREG:
memcpy(&ct->sreg, data, sizeof(ct->sreg));
break;
- default:
- return -1;
}
return 0;
}
@@ -223,14 +221,14 @@ static inline int str2ctdir(const char *str, uint8_t *ctdir)
}
static int
-nftnl_expr_ct_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_ct_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int ret, remain = size, offset = 0;
struct nftnl_expr_ct *ct = nftnl_expr_data(e);
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_CT_SREG)) {
- ret = snprintf(buf, size, "set %s with reg %u ",
+ ret = snprintf(buf, remain, "set %s with reg %u ",
ctkey2str(ct->key), ct->sreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -250,28 +248,21 @@ nftnl_expr_ct_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_ct_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_ct_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy ct_attr_policy[__NFTNL_EXPR_CT_MAX] = {
+ [NFTNL_EXPR_CT_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_CT_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_CT_DIR] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_EXPR_CT_SREG] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_ct = {
.name = "ct",
.alloc_len = sizeof(struct nftnl_expr_ct),
- .max_attr = NFTA_CT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_CT_MAX - 1,
+ .attr_policy = ct_attr_policy,
.set = nftnl_expr_ct_set,
.get = nftnl_expr_ct_get,
.parse = nftnl_expr_ct_parse,
.build = nftnl_expr_ct_build,
- .snprintf = nftnl_expr_ct_snprintf,
+ .output = nftnl_expr_ct_snprintf,
};
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index 67165fe..d2ccf2e 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -25,14 +25,18 @@
#include "internal.h"
static int
-nftnl_data_reg_value_snprintf_default(char *buf, size_t size,
+nftnl_data_reg_value_snprintf_default(char *buf, size_t remain,
const union nftnl_data_reg *reg,
uint32_t flags)
{
- int remain = size, offset = 0, ret, i;
+ const char *pfx = flags & DATA_F_NOPFX ? "" : "0x";
+ int offset = 0, ret, i;
+
+
for (i = 0; i < div_round_up(reg->len, sizeof(uint32_t)); i++) {
- ret = snprintf(buf + offset, remain, "0x%.8x ", reg->val[i]);
+ ret = snprintf(buf + offset, remain,
+ "%s%.8x ", pfx, reg->val[i]);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -59,38 +63,19 @@ nftnl_data_reg_verdict_snprintf_def(char *buf, size_t size,
int nftnl_data_reg_snprintf(char *buf, size_t size,
const union nftnl_data_reg *reg,
- uint32_t output_format, uint32_t flags,
- int reg_type)
+ uint32_t flags, int reg_type)
{
switch(reg_type) {
case DATA_VALUE:
- switch(output_format) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_data_reg_value_snprintf_default(buf, size,
- reg, flags);
- case NFTNL_OUTPUT_JSON:
- case NFTNL_OUTPUT_XML:
- default:
- break;
- }
- break;
+ return nftnl_data_reg_value_snprintf_default(buf, size,
+ reg, flags);
case DATA_VERDICT:
case DATA_CHAIN:
- switch(output_format) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_data_reg_verdict_snprintf_def(buf, size,
- reg, flags);
- case NFTNL_OUTPUT_JSON:
- case NFTNL_OUTPUT_XML:
- default:
- break;
- }
- break;
+ return nftnl_data_reg_verdict_snprintf_def(buf, size,
+ reg, flags);
default:
- break;
+ return -1;
}
-
- return -1;
}
static int nftnl_data_parse_cb(const struct nlattr *attr, void *data)
@@ -125,6 +110,7 @@ static int nftnl_verdict_parse_cb(const struct nlattr *attr, void *data)
switch(type) {
case NFTA_VERDICT_CODE:
+ case NFTA_VERDICT_CHAIN_ID:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -220,14 +206,16 @@ int nftnl_parse_data(union nftnl_data_reg *data, struct nlattr *attr, int *type)
return ret;
}
-void nftnl_free_verdict(const union nftnl_data_reg *data)
+int nftnl_data_cpy(union nftnl_data_reg *dreg, const void *src, uint32_t len)
{
- switch(data->verdict) {
- case NFT_JUMP:
- case NFT_GOTO:
- xfree(data->chain);
- break;
- default:
- break;
+ int ret = 0;
+
+ if (len > sizeof(dreg->val)) {
+ len = sizeof(dreg->val);
+ ret = -1;
}
+
+ memcpy(dreg->val, src, len);
+ dreg->len = len;
+ return ret;
}
diff --git a/src/expr/dup.c b/src/expr/dup.c
index ac39839..6a5e4ca 100644
--- a/src/expr/dup.c
+++ b/src/expr/dup.c
@@ -37,8 +37,6 @@ static int nftnl_expr_dup_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_DUP_SREG_DEV:
memcpy(&dup->sreg_dev, data, sizeof(dup->sreg_dev));
break;
- default:
- return -1;
}
return 0;
}
@@ -111,47 +109,38 @@ static int nftnl_expr_dup_parse(struct nftnl_expr *e, struct nlattr *attr)
return ret;
}
-static int nftnl_expr_dup_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e,
- uint32_t flags)
+static int nftnl_expr_dup_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int remain = len, offset = 0, ret;
struct nftnl_expr_dup *dup = nftnl_expr_data(e);
+ int offset = 0, ret;
if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_ADDR)) {
- ret = snprintf(buf + offset, len, "sreg_addr %u ", dup->sreg_addr);
+ ret = snprintf(buf + offset, remain, "sreg_addr %u ", dup->sreg_addr);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_EXPR_DUP_SREG_DEV)) {
- ret = snprintf(buf + offset, len, "sreg_dev %u ", dup->sreg_dev);
+ ret = snprintf(buf + offset, remain, "sreg_dev %u ", dup->sreg_dev);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
return offset;
}
-static int nftnl_expr_dup_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_dup_snprintf_default(buf, len, e, flags);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy dup_attr_policy[__NFTNL_EXPR_DUP_MAX] = {
+ [NFTNL_EXPR_DUP_SREG_ADDR] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_DUP_SREG_DEV] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_dup = {
.name = "dup",
.alloc_len = sizeof(struct nftnl_expr_dup),
- .max_attr = NFTA_DUP_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_DUP_MAX - 1,
+ .attr_policy = dup_attr_policy,
.set = nftnl_expr_dup_set,
.get = nftnl_expr_dup_get,
.parse = nftnl_expr_dup_parse,
.build = nftnl_expr_dup_build,
- .snprintf = nftnl_expr_dup_snprintf,
+ .output = nftnl_expr_dup_snprintf,
};
diff --git a/src/expr/dynset.c b/src/expr/dynset.c
index b2d8edc..c1f79b5 100644
--- a/src/expr/dynset.c
+++ b/src/expr/dynset.c
@@ -26,9 +26,10 @@ struct nftnl_expr_dynset {
enum nft_registers sreg_data;
enum nft_dynset_ops op;
uint64_t timeout;
- struct nftnl_expr *expr;
+ struct list_head expr_list;
char *set_name;
uint32_t set_id;
+ uint32_t dynset_flags;
};
static int
@@ -36,6 +37,7 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type,
const void *data, uint32_t data_len)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+ struct nftnl_expr *expr, *next;
switch (type) {
case NFTNL_EXPR_DYNSET_SREG_KEY:
@@ -59,7 +61,14 @@ nftnl_expr_dynset_set(struct nftnl_expr *e, uint16_t type,
memcpy(&dynset->set_id, data, sizeof(dynset->set_id));
break;
case NFTNL_EXPR_DYNSET_EXPR:
- dynset->expr = (void *)data;
+ list_for_each_entry_safe(expr, next, &dynset->expr_list, head)
+ nftnl_expr_free(expr);
+
+ expr = (void *)data;
+ list_add(&expr->head, &dynset->expr_list);
+ break;
+ case NFTNL_EXPR_DYNSET_FLAGS:
+ memcpy(&dynset->dynset_flags, data, sizeof(dynset->dynset_flags));
break;
default:
return -1;
@@ -72,6 +81,7 @@ nftnl_expr_dynset_get(const struct nftnl_expr *e, uint16_t type,
uint32_t *data_len)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+ struct nftnl_expr *expr;
switch (type) {
case NFTNL_EXPR_DYNSET_SREG_KEY:
@@ -93,7 +103,12 @@ nftnl_expr_dynset_get(const struct nftnl_expr *e, uint16_t type,
*data_len = sizeof(dynset->set_id);
return &dynset->set_id;
case NFTNL_EXPR_DYNSET_EXPR:
- return dynset->expr;
+ list_for_each_entry(expr, &dynset->expr_list, head)
+ break;
+ return expr;
+ case NFTNL_EXPR_DYNSET_FLAGS:
+ *data_len = sizeof(dynset->dynset_flags);
+ return &dynset->dynset_flags;
}
return NULL;
}
@@ -111,6 +126,7 @@ static int nftnl_expr_dynset_cb(const struct nlattr *attr, void *data)
case NFTA_DYNSET_SREG_DATA:
case NFTA_DYNSET_SET_ID:
case NFTA_DYNSET_OP:
+ case NFTA_DYNSET_FLAGS:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -137,6 +153,7 @@ nftnl_expr_dynset_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
struct nlattr *nest;
+ int num_exprs = 0;
if (e->flags & (1 << NFTNL_EXPR_DYNSET_SREG_KEY))
mnl_attr_put_u32(nlh, NFTA_DYNSET_SREG_KEY, htonl(dynset->sreg_key));
@@ -150,11 +167,58 @@ nftnl_expr_dynset_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
mnl_attr_put_strz(nlh, NFTA_DYNSET_SET_NAME, dynset->set_name);
if (e->flags & (1 << NFTNL_EXPR_DYNSET_SET_ID))
mnl_attr_put_u32(nlh, NFTA_DYNSET_SET_ID, htonl(dynset->set_id));
- if (e->flags & (1 << NFTNL_EXPR_DYNSET_EXPR)) {
- nest = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPR);
- nftnl_expr_build_payload(nlh, dynset->expr);
- mnl_attr_nest_end(nlh, nest);
+ if (!list_empty(&dynset->expr_list)) {
+ struct nftnl_expr *expr;
+
+ list_for_each_entry(expr, &dynset->expr_list, head)
+ num_exprs++;
+
+ if (num_exprs == 1) {
+ nest = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPR);
+ list_for_each_entry(expr, &dynset->expr_list, head)
+ nftnl_expr_build_payload(nlh, expr);
+ mnl_attr_nest_end(nlh, nest);
+ } else if (num_exprs > 1) {
+ struct nlattr *nest1, *nest2;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_DYNSET_EXPRESSIONS);
+ list_for_each_entry(expr, &dynset->expr_list, head) {
+ nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
+ nftnl_expr_build_payload(nlh, expr);
+ mnl_attr_nest_end(nlh, nest2);
+ }
+ mnl_attr_nest_end(nlh, nest1);
+ }
+ }
+ if (e->flags & (1 << NFTNL_EXPR_DYNSET_FLAGS))
+ mnl_attr_put_u32(nlh, NFTA_DYNSET_FLAGS,
+ htonl(dynset->dynset_flags));
+}
+
+EXPORT_SYMBOL(nftnl_expr_add_expr);
+void nftnl_expr_add_expr(struct nftnl_expr *e, uint32_t type,
+ struct nftnl_expr *expr)
+{
+ struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+
+ list_add_tail(&expr->head, &dynset->expr_list);
+}
+
+EXPORT_SYMBOL(nftnl_expr_expr_foreach);
+int nftnl_expr_expr_foreach(const struct nftnl_expr *e,
+ int (*cb)(struct nftnl_expr *e, void *data),
+ void *data)
+{
+ struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+ struct nftnl_expr *cur, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(cur, tmp, &dynset->expr_list, head) {
+ ret = cb(cur, data);
+ if (ret < 0)
+ return ret;
}
+ return 0;
}
static int
@@ -162,6 +226,7 @@ nftnl_expr_dynset_parse(struct nftnl_expr *e, struct nlattr *attr)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
struct nlattr *tb[NFTA_SET_MAX+1] = {};
+ struct nftnl_expr *expr, *next;
int ret = 0;
if (mnl_attr_parse_nested(attr, nftnl_expr_dynset_cb, tb) < 0)
@@ -195,13 +260,38 @@ nftnl_expr_dynset_parse(struct nftnl_expr *e, struct nlattr *attr)
e->flags |= (1 << NFTNL_EXPR_DYNSET_SET_ID);
}
if (tb[NFTA_DYNSET_EXPR]) {
- e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPR);
- dynset->expr = nftnl_expr_parse(tb[NFTA_DYNSET_EXPR]);
- if (dynset->expr == NULL)
+ expr = nftnl_expr_parse(tb[NFTA_DYNSET_EXPR]);
+ if (expr == NULL)
return -1;
+
+ list_add(&expr->head, &dynset->expr_list);
+ e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPR);
+ } else if (tb[NFTA_DYNSET_EXPRESSIONS]) {
+ struct nlattr *attr2;
+
+ mnl_attr_for_each_nested(attr2, tb[NFTA_DYNSET_EXPRESSIONS]) {
+ if (mnl_attr_get_type(attr2) != NFTA_LIST_ELEM)
+ goto out_dynset_expr;
+
+ expr = nftnl_expr_parse(attr2);
+ if (!expr)
+ goto out_dynset_expr;
+
+ list_add_tail(&expr->head, &dynset->expr_list);
+ }
+ e->flags |= (1 << NFTNL_EXPR_DYNSET_EXPRESSIONS);
+ }
+ if (tb[NFTA_DYNSET_FLAGS]) {
+ dynset->dynset_flags = ntohl(mnl_attr_get_u32(tb[NFTA_DYNSET_FLAGS]));
+ e->flags |= (1 << NFTNL_EXPR_DYNSET_FLAGS);
}
return ret;
+out_dynset_expr:
+ list_for_each_entry_safe(expr, next, &dynset->expr_list, head)
+ nftnl_expr_free(expr);
+
+ return -1;
}
static const char *op2str_array[] = {
@@ -218,12 +308,12 @@ static const char *op2str(enum nft_dynset_ops op)
}
static int
-nftnl_expr_dynset_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_dynset_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
struct nftnl_expr *expr;
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
ret = snprintf(buf, remain, "%s reg_key %u set %s ",
op2str(dynset->op), dynset->sreg_key, dynset->set_name);
@@ -239,8 +329,7 @@ nftnl_expr_dynset_snprintf_default(char *buf, size_t size,
dynset->timeout);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- if (e->flags & (1 << NFTNL_EXPR_DYNSET_EXPR)) {
- expr = dynset->expr;
+ list_for_each_entry(expr, &dynset->expr_list, head) {
ret = snprintf(buf + offset, remain, "expr [ %s ",
expr->ops->name);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
@@ -257,36 +346,45 @@ nftnl_expr_dynset_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_dynset_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
+static void nftnl_expr_dynset_init(const struct nftnl_expr *e)
{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_dynset_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+
+ INIT_LIST_HEAD(&dynset->expr_list);
}
static void nftnl_expr_dynset_free(const struct nftnl_expr *e)
{
struct nftnl_expr_dynset *dynset = nftnl_expr_data(e);
+ struct nftnl_expr *expr, *next;
xfree(dynset->set_name);
+ list_for_each_entry_safe(expr, next, &dynset->expr_list, head)
+ nftnl_expr_free(expr);
}
+static struct attr_policy dynset_attr_policy[__NFTNL_EXPR_DYNSET_MAX] = {
+ [NFTNL_EXPR_DYNSET_SREG_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_DYNSET_SREG_DATA] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_DYNSET_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_DYNSET_TIMEOUT] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_DYNSET_SET_NAME] = { .maxlen = NFT_SET_MAXNAMELEN },
+ [NFTNL_EXPR_DYNSET_SET_ID] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_DYNSET_EXPR] = { .maxlen = 0 },
+ [NFTNL_EXPR_DYNSET_EXPRESSIONS] = { .maxlen = 0 },
+ [NFTNL_EXPR_DYNSET_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_dynset = {
.name = "dynset",
.alloc_len = sizeof(struct nftnl_expr_dynset),
- .max_attr = NFTA_DYNSET_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_DYNSET_MAX - 1,
+ .attr_policy = dynset_attr_policy,
+ .init = nftnl_expr_dynset_init,
.free = nftnl_expr_dynset_free,
.set = nftnl_expr_dynset_set,
.get = nftnl_expr_dynset_get,
.parse = nftnl_expr_dynset_parse,
.build = nftnl_expr_dynset_build,
- .snprintf = nftnl_expr_dynset_snprintf,
+ .output = nftnl_expr_dynset_snprintf,
};
diff --git a/src/expr/exthdr.c b/src/expr/exthdr.c
index e5f714b..93b7521 100644
--- a/src/expr/exthdr.c
+++ b/src/expr/exthdr.c
@@ -66,8 +66,6 @@ nftnl_expr_exthdr_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_EXTHDR_SREG:
memcpy(&exthdr->sreg, data, sizeof(exthdr->sreg));
break;
- default:
- return -1;
}
return 0;
}
@@ -235,8 +233,9 @@ static inline int str2exthdr_type(const char *str)
return -1;
}
-static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_exthdr_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_exthdr *exthdr = nftnl_expr_data(e);
@@ -246,35 +245,36 @@ static int nftnl_expr_exthdr_snprintf_default(char *buf, size_t len,
exthdr->offset,
exthdr->flags & NFT_EXTHDR_F_PRESENT ? " present" : "",
exthdr->dreg);
- else
+ else if (e->flags & (1 << NFTNL_EXPR_EXTHDR_SREG))
return snprintf(buf, len, "write%s reg %u => %ub @ %u + %u ",
op2str(exthdr->op), exthdr->sreg, exthdr->len, exthdr->type,
exthdr->offset);
+ else if (exthdr->op == NFT_EXTHDR_OP_TCPOPT && exthdr->len == 0)
+ return snprintf(buf, len, "reset tcpopt %u ", exthdr->type);
+ else
+ return snprintf(buf, len, "op %u len %u type %u offset %u ",
+ exthdr->op, exthdr->len, exthdr->type, exthdr->offset);
}
-static int
-nftnl_expr_exthdr_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_exthdr_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy exthdr_attr_policy[__NFTNL_EXPR_EXTHDR_MAX] = {
+ [NFTNL_EXPR_EXTHDR_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_EXTHDR_TYPE] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_EXPR_EXTHDR_OFFSET] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_EXTHDR_LEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_EXTHDR_FLAGS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_EXTHDR_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_EXTHDR_SREG] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_exthdr = {
.name = "exthdr",
.alloc_len = sizeof(struct nftnl_expr_exthdr),
- .max_attr = NFTA_EXTHDR_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_EXTHDR_MAX - 1,
+ .attr_policy = exthdr_attr_policy,
.set = nftnl_expr_exthdr_set,
.get = nftnl_expr_exthdr_get,
.parse = nftnl_expr_exthdr_parse,
.build = nftnl_expr_exthdr_build,
- .snprintf = nftnl_expr_exthdr_snprintf,
+ .output = nftnl_expr_exthdr_snprintf,
};
diff --git a/src/expr/fib.c b/src/expr/fib.c
index 9475af4..5f7bef4 100644
--- a/src/expr/fib.c
+++ b/src/expr/fib.c
@@ -43,8 +43,6 @@ nftnl_expr_fib_set(struct nftnl_expr *e, uint16_t result,
case NFTNL_EXPR_FIB_FLAGS:
memcpy(&fib->flags, data, sizeof(fib->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -143,13 +141,13 @@ static const char *fib_type_str(enum nft_fib_result r)
}
static int
-nftnl_expr_fib_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_fib_snprintf(char *buf, size_t remain,
+ uint32_t printflags, const struct nftnl_expr *e)
{
struct nftnl_expr_fib *fib = nftnl_expr_data(e);
- int remain = size, offset = 0, ret, i;
uint32_t flags = fib->flags & ~NFTA_FIB_F_PRESENT;
uint32_t present_flag = fib->flags & NFTA_FIB_F_PRESENT;
+ int offset = 0, ret, i;
static const struct {
int bit;
const char *name;
@@ -190,28 +188,20 @@ nftnl_expr_fib_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_fib_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_fib_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy fib_attr_policy[__NFTNL_EXPR_FIB_MAX] = {
+ [NFTNL_EXPR_FIB_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_FIB_RESULT] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_FIB_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_fib = {
.name = "fib",
.alloc_len = sizeof(struct nftnl_expr_fib),
- .max_attr = NFTA_FIB_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_FIB_MAX - 1,
+ .attr_policy = fib_attr_policy,
.set = nftnl_expr_fib_set,
.get = nftnl_expr_fib_get,
.parse = nftnl_expr_fib_parse,
.build = nftnl_expr_fib_build,
- .snprintf = nftnl_expr_fib_snprintf,
+ .output = nftnl_expr_fib_snprintf,
};
diff --git a/src/expr/flow_offload.c b/src/expr/flow_offload.c
index 6ccec9a..5f209a6 100644
--- a/src/expr/flow_offload.c
+++ b/src/expr/flow_offload.c
@@ -25,8 +25,6 @@ static int nftnl_expr_flow_set(struct nftnl_expr *e, uint16_t type,
if (!flow->table_name)
return -1;
break;
- default:
- return -1;
}
return 0;
}
@@ -92,11 +90,11 @@ static int nftnl_expr_flow_parse(struct nftnl_expr *e, struct nlattr *attr)
return ret;
}
-static int nftnl_expr_flow_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int nftnl_expr_flow_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int remain = size, offset = 0, ret;
struct nftnl_expr_flow *l = nftnl_expr_data(e);
+ int offset = 0, ret;
ret = snprintf(buf, remain, "flowtable %s ", l->table_name);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
@@ -104,20 +102,6 @@ static int nftnl_expr_flow_snprintf_default(char *buf, size_t size,
return offset;
}
-static int nftnl_expr_flow_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_flow_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
static void nftnl_expr_flow_free(const struct nftnl_expr *e)
{
struct nftnl_expr_flow *flow = nftnl_expr_data(e);
@@ -125,14 +109,19 @@ static void nftnl_expr_flow_free(const struct nftnl_expr *e)
xfree(flow->table_name);
}
+static struct attr_policy flow_offload_attr_policy[__NFTNL_EXPR_FLOW_MAX] = {
+ [NFTNL_EXPR_FLOW_TABLE_NAME] = { .maxlen = NFT_NAME_MAXLEN },
+};
+
struct expr_ops expr_ops_flow = {
.name = "flow_offload",
.alloc_len = sizeof(struct nftnl_expr_flow),
- .max_attr = NFTA_FLOW_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_FLOW_MAX - 1,
+ .attr_policy = flow_offload_attr_policy,
.free = nftnl_expr_flow_free,
.set = nftnl_expr_flow_set,
.get = nftnl_expr_flow_get,
.parse = nftnl_expr_flow_parse,
.build = nftnl_expr_flow_build,
- .snprintf = nftnl_expr_flow_snprintf,
+ .output = nftnl_expr_flow_snprintf,
};
diff --git a/src/expr/fwd.c b/src/expr/fwd.c
index 2ec63c1..566d6f4 100644
--- a/src/expr/fwd.c
+++ b/src/expr/fwd.c
@@ -41,8 +41,6 @@ static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_FWD_NFPROTO:
memcpy(&fwd->nfproto, data, sizeof(fwd->nfproto));
break;
- default:
- return -1;
}
return 0;
}
@@ -125,12 +123,11 @@ static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr)
return ret;
}
-static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e,
- uint32_t flags)
+static int nftnl_expr_fwd_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int remain = len, offset = 0, ret;
struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
+ int offset = 0, ret;
if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV)) {
ret = snprintf(buf + offset, remain, "sreg_dev %u ",
@@ -151,27 +148,20 @@ static int nftnl_expr_fwd_snprintf_default(char *buf, size_t len,
return offset;
}
-static int nftnl_expr_fwd_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_fwd_snprintf_default(buf, len, e, flags);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy fwd_attr_policy[__NFTNL_EXPR_FWD_MAX] = {
+ [NFTNL_EXPR_FWD_SREG_DEV] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_FWD_SREG_ADDR] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_FWD_NFPROTO] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_fwd = {
.name = "fwd",
.alloc_len = sizeof(struct nftnl_expr_fwd),
- .max_attr = NFTA_FWD_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_FWD_MAX - 1,
+ .attr_policy = fwd_attr_policy,
.set = nftnl_expr_fwd_set,
.get = nftnl_expr_fwd_get,
.parse = nftnl_expr_fwd_parse,
.build = nftnl_expr_fwd_build,
- .snprintf = nftnl_expr_fwd_snprintf,
+ .output = nftnl_expr_fwd_snprintf,
};
diff --git a/src/expr/hash.c b/src/expr/hash.c
index 2c801d2..4cd9006 100644
--- a/src/expr/hash.c
+++ b/src/expr/hash.c
@@ -184,11 +184,11 @@ nftnl_expr_hash_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_hash_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_hash_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_hash *hash = nftnl_expr_data(e);
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
switch (hash->type) {
case NFT_HASH_SYM:
@@ -218,28 +218,24 @@ nftnl_expr_hash_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_hash_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_hash_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy hash_attr_policy[__NFTNL_EXPR_HASH_MAX] = {
+ [NFTNL_EXPR_HASH_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_LEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_MODULUS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_SEED] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_OFFSET] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_HASH_TYPE] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_hash = {
.name = "hash",
.alloc_len = sizeof(struct nftnl_expr_hash),
- .max_attr = NFTA_HASH_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_HASH_MAX - 1,
+ .attr_policy = hash_attr_policy,
.set = nftnl_expr_hash_set,
.get = nftnl_expr_hash_get,
.parse = nftnl_expr_hash_parse,
.build = nftnl_expr_hash_build,
- .snprintf = nftnl_expr_hash_snprintf,
+ .output = nftnl_expr_hash_snprintf,
};
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index 47106ae..b77ccea 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -36,9 +36,7 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type,
memcpy(&imm->dreg, data, sizeof(imm->dreg));
break;
case NFTNL_EXPR_IMM_DATA:
- memcpy(&imm->data.val, data, data_len);
- imm->data.len = data_len;
- break;
+ return nftnl_data_cpy(&imm->data, data, data_len);
case NFTNL_EXPR_IMM_VERDICT:
memcpy(&imm->data.verdict, data, sizeof(imm->data.verdict));
break;
@@ -50,8 +48,9 @@ nftnl_expr_immediate_set(struct nftnl_expr *e, uint16_t type,
if (!imm->data.chain)
return -1;
break;
- default:
- return -1;
+ case NFTNL_EXPR_IMM_CHAIN_ID:
+ memcpy(&imm->data.chain_id, data, sizeof(uint32_t));
+ break;
}
return 0;
}
@@ -75,6 +74,9 @@ nftnl_expr_immediate_get(const struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_IMM_CHAIN:
*data_len = strlen(imm->data.chain)+1;
return imm->data.chain;
+ case NFTNL_EXPR_IMM_CHAIN_ID:
+ *data_len = sizeof(imm->data.chain_id);
+ return &imm->data.chain_id;
}
return NULL;
}
@@ -126,6 +128,10 @@ nftnl_expr_immediate_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(imm->data.verdict));
if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN))
mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, imm->data.chain);
+ if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN_ID)) {
+ mnl_attr_put_u32(nlh, NFTA_VERDICT_CHAIN_ID,
+ htonl(imm->data.chain_id));
+ }
mnl_attr_nest_end(nlh, nest1);
mnl_attr_nest_end(nlh, nest2);
@@ -174,66 +180,59 @@ nftnl_expr_immediate_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_immediate_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e,
- uint32_t flags)
+nftnl_expr_immediate_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int remain = len, offset = 0, ret;
struct nftnl_expr_immediate *imm = nftnl_expr_data(e);
+ int offset = 0, ret;
ret = snprintf(buf, remain, "reg %u ", imm->dreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (e->flags & (1 << NFTNL_EXPR_IMM_DATA)) {
ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
- NFTNL_OUTPUT_DEFAULT, flags, DATA_VALUE);
+ flags, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
} else if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT)) {
ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
- NFTNL_OUTPUT_DEFAULT, flags, DATA_VERDICT);
+ flags, DATA_VERDICT);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
} else if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN)) {
ret = nftnl_data_reg_snprintf(buf + offset, remain, &imm->data,
- NFTNL_OUTPUT_DEFAULT, flags, DATA_CHAIN);
+ flags, DATA_CHAIN);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
return offset;
}
-static int
-nftnl_expr_immediate_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_immediate_snprintf_default(buf, len, e, flags);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
static void nftnl_expr_immediate_free(const struct nftnl_expr *e)
{
struct nftnl_expr_immediate *imm = nftnl_expr_data(e);
- if (e->flags & (1 << NFTNL_EXPR_IMM_VERDICT))
- nftnl_free_verdict(&imm->data);
+ if (e->flags & (1 << NFTNL_EXPR_IMM_CHAIN))
+ xfree(imm->data.chain);
}
+static struct attr_policy immediate_attr_policy[__NFTNL_EXPR_IMM_MAX] = {
+ [NFTNL_EXPR_IMM_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_IMM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+ [NFTNL_EXPR_IMM_VERDICT] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_IMM_CHAIN] = { .maxlen = NFT_CHAIN_MAXNAMELEN },
+ [NFTNL_EXPR_IMM_CHAIN_ID] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_immediate = {
.name = "immediate",
.alloc_len = sizeof(struct nftnl_expr_immediate),
- .max_attr = NFTA_IMMEDIATE_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_IMM_MAX - 1,
+ .attr_policy = immediate_attr_policy,
.free = nftnl_expr_immediate_free,
.set = nftnl_expr_immediate_set,
.get = nftnl_expr_immediate_get,
.parse = nftnl_expr_immediate_parse,
.build = nftnl_expr_immediate_build,
- .snprintf = nftnl_expr_immediate_snprintf,
+ .output = nftnl_expr_immediate_snprintf,
};
diff --git a/src/expr/inner.c b/src/expr/inner.c
new file mode 100644
index 0000000..45ef4fb
--- /dev/null
+++ b/src/expr/inner.c
@@ -0,0 +1,220 @@
+/*
+ * (C) 2012-2022 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <libmnl/libmnl.h>
+
+#include <linux/netfilter/nf_tables.h>
+
+#include <libnftnl/expr.h>
+#include <libnftnl/rule.h>
+
+struct nftnl_expr_inner {
+ uint32_t type;
+ uint32_t flags;
+ uint32_t hdrsize;
+ struct nftnl_expr *expr;
+};
+
+static void nftnl_expr_inner_free(const struct nftnl_expr *e)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+
+ if (inner->expr)
+ nftnl_expr_free(inner->expr);
+}
+
+static int
+nftnl_expr_inner_set(struct nftnl_expr *e, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+
+ switch(type) {
+ case NFTNL_EXPR_INNER_TYPE:
+ memcpy(&inner->type, data, sizeof(inner->type));
+ break;
+ case NFTNL_EXPR_INNER_FLAGS:
+ memcpy(&inner->flags, data, sizeof(inner->flags));
+ break;
+ case NFTNL_EXPR_INNER_HDRSIZE:
+ memcpy(&inner->hdrsize, data, sizeof(inner->hdrsize));
+ break;
+ case NFTNL_EXPR_INNER_EXPR:
+ if (inner->expr)
+ nftnl_expr_free(inner->expr);
+
+ inner->expr = (void *)data;
+ break;
+ }
+ return 0;
+}
+
+static const void *
+nftnl_expr_inner_get(const struct nftnl_expr *e, uint16_t type,
+ uint32_t *data_len)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+
+ switch(type) {
+ case NFTNL_EXPR_INNER_FLAGS:
+ *data_len = sizeof(inner->flags);
+ return &inner->flags;
+ case NFTNL_EXPR_INNER_TYPE:
+ *data_len = sizeof(inner->type);
+ return &inner->type;
+ case NFTNL_EXPR_INNER_HDRSIZE:
+ *data_len = sizeof(inner->hdrsize);
+ return &inner->hdrsize;
+ case NFTNL_EXPR_INNER_EXPR:
+ return inner->expr;
+ }
+ return NULL;
+}
+
+static void
+nftnl_expr_inner_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+ struct nlattr *nest;
+
+ mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0));
+ if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE))
+ mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type));
+ if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS))
+ mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags));
+ if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE))
+ mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize));
+ if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) {
+ nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR);
+ nftnl_expr_build_payload(nlh, inner->expr);
+ mnl_attr_nest_end(nlh, nest);
+ }
+}
+
+static int nftnl_inner_parse_cb(const struct nlattr *attr, void *data)
+{
+ const struct nlattr **tb = data;
+ int type = mnl_attr_get_type(attr);
+
+ if (mnl_attr_type_valid(attr, NFTA_INNER_MAX) < 0)
+ return MNL_CB_OK;
+
+ switch(type) {
+ case NFTA_INNER_NUM:
+ case NFTA_INNER_TYPE:
+ case NFTA_INNER_HDRSIZE:
+ case NFTA_INNER_FLAGS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ abi_breakage();
+ break;
+ case NFTA_INNER_EXPR:
+ if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
+ abi_breakage();
+ break;
+ }
+
+ tb[type] = attr;
+
+ return MNL_CB_OK;
+}
+
+static int
+nftnl_expr_inner_parse(struct nftnl_expr *e, struct nlattr *attr)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+ struct nlattr *tb[NFTA_INNER_MAX + 1] = {};
+ struct nftnl_expr *expr;
+ int err;
+
+ err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb);
+ if (err < 0)
+ return err;
+
+ if (tb[NFTA_INNER_HDRSIZE]) {
+ inner->hdrsize =
+ ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE]));
+ e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE);
+ }
+ if (tb[NFTA_INNER_FLAGS]) {
+ inner->flags =
+ ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS]));
+ e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS);
+ }
+ if (tb[NFTA_INNER_TYPE]) {
+ inner->type =
+ ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE]));
+ e->flags |= (1 << NFTNL_EXPR_INNER_TYPE);
+ }
+ if (tb[NFTA_INNER_EXPR]) {
+ expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]);
+ if (!expr)
+ return -1;
+
+ if (inner->expr)
+ nftnl_expr_free(inner->expr);
+
+ inner->expr = expr;
+ e->flags |= (1 << NFTNL_EXPR_INNER_EXPR);
+ }
+
+ return 0;
+}
+
+static int
+nftnl_expr_inner_snprintf(char *buf, size_t remain, uint32_t flags,
+ const struct nftnl_expr *e)
+{
+ struct nftnl_expr_inner *inner = nftnl_expr_data(e);
+ uint32_t offset = 0;
+ int ret;
+
+ ret = snprintf(buf, remain, "type %u hdrsize %u flags %x [",
+ inner->type, inner->hdrsize, inner->flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ ret = snprintf(buf + offset, remain, " %s ", inner->expr->ops->name);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr,
+ NFTNL_OUTPUT_DEFAULT, 0);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ ret = snprintf(buf + offset, remain, "] ");
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ return offset;
+}
+
+static struct attr_policy inner_attr_policy[__NFTNL_EXPR_INNER_MAX] = {
+ [NFTNL_EXPR_INNER_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_INNER_FLAGS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_INNER_HDRSIZE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_INNER_EXPR] = { .maxlen = 0 },
+};
+
+struct expr_ops expr_ops_inner = {
+ .name = "inner",
+ .alloc_len = sizeof(struct nftnl_expr_inner),
+ .nftnl_max_attr = __NFTNL_EXPR_INNER_MAX - 1,
+ .attr_policy = inner_attr_policy,
+ .free = nftnl_expr_inner_free,
+ .set = nftnl_expr_inner_set,
+ .get = nftnl_expr_inner_get,
+ .parse = nftnl_expr_inner_parse,
+ .build = nftnl_expr_inner_build,
+ .output = nftnl_expr_inner_snprintf,
+};
diff --git a/src/expr/last.c b/src/expr/last.c
new file mode 100644
index 0000000..074f463
--- /dev/null
+++ b/src/expr/last.c
@@ -0,0 +1,142 @@
+/*
+ * (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <linux/netfilter/nf_tables.h>
+
+#include "internal.h"
+#include <libmnl/libmnl.h>
+#include <libnftnl/expr.h>
+#include <libnftnl/rule.h>
+
+struct nftnl_expr_last {
+ uint64_t msecs;
+ uint32_t set;
+};
+
+static int nftnl_expr_last_set(struct nftnl_expr *e, uint16_t type,
+ const void *data, uint32_t data_len)
+{
+ struct nftnl_expr_last *last = nftnl_expr_data(e);
+
+ switch (type) {
+ case NFTNL_EXPR_LAST_MSECS:
+ memcpy(&last->msecs, data, sizeof(last->msecs));
+ break;
+ case NFTNL_EXPR_LAST_SET:
+ memcpy(&last->set, data, sizeof(last->set));
+ break;
+ }
+ return 0;
+}
+
+static const void *nftnl_expr_last_get(const struct nftnl_expr *e,
+ uint16_t type, uint32_t *data_len)
+{
+ struct nftnl_expr_last *last = nftnl_expr_data(e);
+
+ switch (type) {
+ case NFTNL_EXPR_LAST_MSECS:
+ *data_len = sizeof(last->msecs);
+ return &last->msecs;
+ case NFTNL_EXPR_LAST_SET:
+ *data_len = sizeof(last->set);
+ return &last->set;
+ }
+ return NULL;
+}
+
+static int nftnl_expr_last_cb(const struct nlattr *attr, void *data)
+{
+ int type = mnl_attr_get_type(attr);
+ const struct nlattr **tb = data;
+
+ if (mnl_attr_type_valid(attr, NFTA_LAST_MAX) < 0)
+ return MNL_CB_OK;
+
+ switch(type) {
+ case NFTA_LAST_MSECS:
+ if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
+ abi_breakage();
+ break;
+ case NFTA_LAST_SET:
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+ abi_breakage();
+ break;
+ }
+
+ tb[type] = attr;
+ return MNL_CB_OK;
+}
+
+static void
+nftnl_expr_last_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
+{
+ struct nftnl_expr_last *last = nftnl_expr_data(e);
+
+ if (e->flags & (1 << NFTNL_EXPR_LAST_MSECS))
+ mnl_attr_put_u64(nlh, NFTA_LAST_MSECS, htobe64(last->msecs));
+ if (e->flags & (1 << NFTNL_EXPR_LAST_SET))
+ mnl_attr_put_u32(nlh, NFTA_LAST_SET, htonl(last->set));
+}
+
+static int
+nftnl_expr_last_parse(struct nftnl_expr *e, struct nlattr *attr)
+{
+ struct nftnl_expr_last *last = nftnl_expr_data(e);
+ struct nlattr *tb[NFTA_LAST_MAX + 1] = {};
+
+ if (mnl_attr_parse_nested(attr, nftnl_expr_last_cb, tb) < 0)
+ return -1;
+
+ if (tb[NFTA_LAST_MSECS]) {
+ last->msecs = be64toh(mnl_attr_get_u64(tb[NFTA_LAST_MSECS]));
+ e->flags |= (1 << NFTNL_EXPR_LAST_MSECS);
+ }
+ if (tb[NFTA_LAST_SET]) {
+ last->set = ntohl(mnl_attr_get_u32(tb[NFTA_LAST_SET]));
+ e->flags |= (1 << NFTNL_EXPR_LAST_SET);
+ }
+
+ return 0;
+}
+
+static int nftnl_expr_last_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_expr *e)
+{
+ struct nftnl_expr_last *last = nftnl_expr_data(e);
+
+ if (!last->set)
+ return snprintf(buf, len, "never ");
+
+ return snprintf(buf, len, "%"PRIu64" ", last->msecs);
+}
+
+static struct attr_policy last_attr_policy[__NFTNL_EXPR_LAST_MAX] = {
+ [NFTNL_EXPR_LAST_MSECS] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_LAST_SET] = { .maxlen = sizeof(uint32_t) },
+};
+
+struct expr_ops expr_ops_last = {
+ .name = "last",
+ .alloc_len = sizeof(struct nftnl_expr_last),
+ .nftnl_max_attr = __NFTNL_EXPR_LAST_MAX - 1,
+ .attr_policy = last_attr_policy,
+ .set = nftnl_expr_last_set,
+ .get = nftnl_expr_last_get,
+ .parse = nftnl_expr_last_parse,
+ .build = nftnl_expr_last_build,
+ .output = nftnl_expr_last_snprintf,
+};
diff --git a/src/expr/limit.c b/src/expr/limit.c
index 5872e27..935d449 100644
--- a/src/expr/limit.c
+++ b/src/expr/limit.c
@@ -52,8 +52,6 @@ nftnl_expr_limit_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_LIMIT_FLAGS:
memcpy(&limit->flags, data, sizeof(limit->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -183,8 +181,9 @@ static const char *limit_to_type(enum nft_limit_type type)
}
}
-static int nftnl_expr_limit_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_limit_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_limit *limit = nftnl_expr_data(e);
@@ -193,28 +192,22 @@ static int nftnl_expr_limit_snprintf_default(char *buf, size_t len,
limit_to_type(limit->type), limit->flags);
}
-static int
-nftnl_expr_limit_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_limit_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy limit_attr_policy[__NFTNL_EXPR_LIMIT_MAX] = {
+ [NFTNL_EXPR_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_limit = {
.name = "limit",
.alloc_len = sizeof(struct nftnl_expr_limit),
- .max_attr = NFTA_LIMIT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_LIMIT_MAX - 1,
+ .attr_policy = limit_attr_policy,
.set = nftnl_expr_limit_set,
.get = nftnl_expr_limit_get,
.parse = nftnl_expr_limit_parse,
.build = nftnl_expr_limit_build,
- .snprintf = nftnl_expr_limit_snprintf,
+ .output = nftnl_expr_limit_snprintf,
};
diff --git a/src/expr/log.c b/src/expr/log.c
index bbe43d2..d6d6910 100644
--- a/src/expr/log.c
+++ b/src/expr/log.c
@@ -60,8 +60,6 @@ static int nftnl_expr_log_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_LOG_FLAGS:
memcpy(&log->flags, data, sizeof(log->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -186,11 +184,12 @@ nftnl_expr_log_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_log_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_log_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_log *log = nftnl_expr_data(e);
- int ret, offset = 0, remain = size;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_LOG_PREFIX)) {
ret = snprintf(buf, remain, "prefix %s ", log->prefix);
@@ -236,21 +235,6 @@ static int nftnl_expr_log_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_log_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_log_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
static void nftnl_expr_log_free(const struct nftnl_expr *e)
{
struct nftnl_expr_log *log = nftnl_expr_data(e);
@@ -258,14 +242,24 @@ static void nftnl_expr_log_free(const struct nftnl_expr *e)
xfree(log->prefix);
}
+static struct attr_policy log_attr_policy[__NFTNL_EXPR_LOG_MAX] = {
+ [NFTNL_EXPR_LOG_PREFIX] = { .maxlen = NF_LOG_PREFIXLEN },
+ [NFTNL_EXPR_LOG_GROUP] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_LOG_SNAPLEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LOG_QTHRESHOLD] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_LOG_LEVEL] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LOG_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_log = {
.name = "log",
.alloc_len = sizeof(struct nftnl_expr_log),
- .max_attr = NFTA_LOG_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_LOG_MAX - 1,
+ .attr_policy = log_attr_policy,
.free = nftnl_expr_log_free,
.set = nftnl_expr_log_set,
.get = nftnl_expr_log_get,
.parse = nftnl_expr_log_parse,
.build = nftnl_expr_log_build,
- .snprintf = nftnl_expr_log_snprintf,
+ .output = nftnl_expr_log_snprintf,
};
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index a495ac0..be04528 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -53,8 +53,6 @@ nftnl_expr_lookup_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_LOOKUP_FLAGS:
memcpy(&lookup->flags, data, sizeof(lookup->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -168,11 +166,11 @@ nftnl_expr_lookup_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_lookup_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_lookup_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int remain = size, offset = 0, ret;
struct nftnl_expr_lookup *l = nftnl_expr_data(e);
+ int offset = 0, ret;
ret = snprintf(buf, remain, "reg %u set %s ", l->sreg, l->set_name);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
@@ -190,21 +188,6 @@ nftnl_expr_lookup_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_lookup_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_lookup_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
static void nftnl_expr_lookup_free(const struct nftnl_expr *e)
{
struct nftnl_expr_lookup *lookup = nftnl_expr_data(e);
@@ -212,14 +195,23 @@ static void nftnl_expr_lookup_free(const struct nftnl_expr *e)
xfree(lookup->set_name);
}
+static struct attr_policy lookup_attr_policy[__NFTNL_EXPR_LOOKUP_MAX] = {
+ [NFTNL_EXPR_LOOKUP_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LOOKUP_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LOOKUP_SET] = { .maxlen = NFT_SET_MAXNAMELEN },
+ [NFTNL_EXPR_LOOKUP_SET_ID] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_LOOKUP_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_lookup = {
.name = "lookup",
.alloc_len = sizeof(struct nftnl_expr_lookup),
- .max_attr = NFTA_LOOKUP_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_LOOKUP_MAX - 1,
+ .attr_policy = lookup_attr_policy,
.free = nftnl_expr_lookup_free,
.set = nftnl_expr_lookup_set,
.get = nftnl_expr_lookup_get,
.parse = nftnl_expr_lookup_parse,
.build = nftnl_expr_lookup_build,
- .snprintf = nftnl_expr_lookup_snprintf,
+ .output = nftnl_expr_lookup_snprintf,
};
diff --git a/src/expr/masq.c b/src/expr/masq.c
index f6f3ceb..4be5a9c 100644
--- a/src/expr/masq.c
+++ b/src/expr/masq.c
@@ -42,8 +42,6 @@ nftnl_expr_masq_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_MASQ_REG_PROTO_MAX:
memcpy(&masq->sreg_proto_max, data, sizeof(masq->sreg_proto_max));
break;
- default:
- return -1;
}
return 0;
}
@@ -131,43 +129,44 @@ nftnl_expr_masq_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_masq_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int nftnl_expr_masq_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_masq *masq = nftnl_expr_data(e);
+ int offset = 0, ret = 0;
- if (e->flags & (1 << NFTNL_EXPR_MASQ_FLAGS))
- return snprintf(buf, len, "flags 0x%x ", masq->flags);
if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MIN)) {
- return snprintf(buf, len,
- "proto_min reg %u proto_max reg %u ",
- masq->sreg_proto_min, masq->sreg_proto_max);
+ ret = snprintf(buf + offset, remain, "proto_min reg %u ",
+ masq->sreg_proto_min);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+ if (e->flags & (1 << NFTNL_EXPR_MASQ_REG_PROTO_MAX)) {
+ ret = snprintf(buf + offset, remain, "proto_max reg %u ",
+ masq->sreg_proto_max);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+ if (e->flags & (1 << NFTNL_EXPR_MASQ_FLAGS)) {
+ ret = snprintf(buf + offset, remain, "flags 0x%x ", masq->flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- return 0;
+ return offset;
}
-static int nftnl_expr_masq_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_masq_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy masq_attr_policy[__NFTNL_EXPR_MASQ_MAX] = {
+ [NFTNL_EXPR_MASQ_FLAGS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_MASQ_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_MASQ_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_masq = {
.name = "masq",
.alloc_len = sizeof(struct nftnl_expr_masq),
- .max_attr = NFTA_MASQ_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_MASQ_MAX - 1,
+ .attr_policy = masq_attr_policy,
.set = nftnl_expr_masq_set,
.get = nftnl_expr_masq_get,
.parse = nftnl_expr_masq_parse,
.build = nftnl_expr_masq_build,
- .snprintf = nftnl_expr_masq_snprintf,
+ .output = nftnl_expr_masq_snprintf,
};
diff --git a/src/expr/match.c b/src/expr/match.c
index 4fa74b2..68288dc 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -55,8 +55,6 @@ nftnl_expr_match_set(struct nftnl_expr *e, uint16_t type,
mt->data = data;
mt->data_len = data_len;
break;
- default:
- return -1;
}
return 0;
}
@@ -165,21 +163,12 @@ static int nftnl_expr_match_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_match_snprintf(char *buf, size_t len, uint32_t type,
+nftnl_expr_match_snprintf(char *buf, size_t len,
uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_match *match = nftnl_expr_data(e);
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return snprintf(buf, len, "name %s rev %u ",
- match->name, match->rev);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ return snprintf(buf, len, "name %s rev %u ", match->name, match->rev);
}
static void nftnl_expr_match_free(const struct nftnl_expr *e)
@@ -189,14 +178,21 @@ static void nftnl_expr_match_free(const struct nftnl_expr *e)
xfree(match->data);
}
+static struct attr_policy match_attr_policy[__NFTNL_EXPR_MT_MAX] = {
+ [NFTNL_EXPR_MT_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN },
+ [NFTNL_EXPR_MT_REV] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_MT_INFO] = { .maxlen = 0 },
+};
+
struct expr_ops expr_ops_match = {
.name = "match",
.alloc_len = sizeof(struct nftnl_expr_match),
- .max_attr = NFTA_MATCH_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_MT_MAX - 1,
+ .attr_policy = match_attr_policy,
.free = nftnl_expr_match_free,
.set = nftnl_expr_match_set,
.get = nftnl_expr_match_get,
.parse = nftnl_expr_match_parse,
.build = nftnl_expr_match_build,
- .snprintf = nftnl_expr_match_snprintf,
+ .output = nftnl_expr_match_snprintf,
};
diff --git a/src/expr/meta.c b/src/expr/meta.c
index 6ed8ee5..cd49c34 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -22,7 +22,7 @@
#include <libnftnl/rule.h>
#ifndef NFT_META_MAX
-#define NFT_META_MAX (NFT_META_SDIFNAME + 1)
+#define NFT_META_MAX (NFT_META_BRI_BROUTE + 1)
#endif
struct nftnl_expr_meta {
@@ -47,8 +47,6 @@ nftnl_expr_meta_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_META_SREG:
memcpy(&meta->sreg, data, sizeof(meta->sreg));
break;
- default:
- return -1;
}
return 0;
}
@@ -168,6 +166,7 @@ static const char *meta_key2str_array[NFT_META_MAX] = {
[NFT_META_TIME_HOUR] = "hour",
[NFT_META_SDIF] = "sdif",
[NFT_META_SDIFNAME] = "sdifname",
+ [NFT_META_BRI_BROUTE] = "broute",
};
static const char *meta_key2str(uint8_t key)
@@ -192,8 +191,8 @@ static inline int str2meta_key(const char *str)
}
static int
-nftnl_expr_meta_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+nftnl_expr_meta_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_meta *meta = nftnl_expr_data(e);
@@ -208,28 +207,20 @@ nftnl_expr_meta_snprintf_default(char *buf, size_t len,
return 0;
}
-static int
-nftnl_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_meta_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy meta_attr_policy[__NFTNL_EXPR_META_MAX] = {
+ [NFTNL_EXPR_META_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_META_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_META_SREG] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_meta = {
.name = "meta",
.alloc_len = sizeof(struct nftnl_expr_meta),
- .max_attr = NFTA_META_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_META_MAX - 1,
+ .attr_policy = meta_attr_policy,
.set = nftnl_expr_meta_set,
.get = nftnl_expr_meta_get,
.parse = nftnl_expr_meta_parse,
.build = nftnl_expr_meta_build,
- .snprintf = nftnl_expr_meta_snprintf,
+ .output = nftnl_expr_meta_snprintf,
};
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 6b7d50e..f3f8644 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -62,8 +62,6 @@ nftnl_expr_nat_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_NAT_FLAGS:
memcpy(&nat->flags, data, sizeof(nat->flags));
break;
- default:
- return -1;
}
return 0;
@@ -221,11 +219,11 @@ static inline int nftnl_str2nat(const char *nat)
}
static int
-nftnl_expr_nat_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_nat_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_nat *nat = nftnl_expr_data(e);
- int remain = size, offset = 0, ret = 0;
+ int offset = 0, ret = 0;
ret = snprintf(buf, remain, "%s ", nat2str(nat->type));
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
@@ -236,48 +234,54 @@ nftnl_expr_nat_snprintf_default(char *buf, size_t size,
if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MIN)) {
ret = snprintf(buf + offset, remain,
- "addr_min reg %u addr_max reg %u ",
- nat->sreg_addr_min, nat->sreg_addr_max);
+ "addr_min reg %u ", nat->sreg_addr_min);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+
+ if (e->flags & (1 << NFTNL_EXPR_NAT_REG_ADDR_MAX)) {
+ ret = snprintf(buf + offset, remain,
+ "addr_max reg %u ", nat->sreg_addr_max);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MIN)) {
ret = snprintf(buf + offset, remain,
- "proto_min reg %u proto_max reg %u ",
- nat->sreg_proto_min, nat->sreg_proto_max);
+ "proto_min reg %u ", nat->sreg_proto_min);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ }
+
+ if (e->flags & (1 << NFTNL_EXPR_NAT_REG_PROTO_MAX)) {
+ ret = snprintf(buf + offset, remain,
+ "proto_max reg %u ", nat->sreg_proto_max);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_EXPR_NAT_FLAGS)) {
- ret = snprintf(buf + offset, remain, "flags %u", nat->flags);
+ ret = snprintf(buf + offset, remain, "flags 0x%x ", nat->flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
return offset;
}
-static int
-nftnl_expr_nat_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_nat_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy nat_attr_policy[__NFTNL_EXPR_NAT_MAX] = {
+ [NFTNL_EXPR_NAT_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_FAMILY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_REG_ADDR_MIN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_REG_ADDR_MAX] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NAT_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_nat = {
.name = "nat",
.alloc_len = sizeof(struct nftnl_expr_nat),
- .max_attr = NFTA_NAT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_NAT_MAX - 1,
+ .attr_policy = nat_attr_policy,
.set = nftnl_expr_nat_set,
.get = nftnl_expr_nat_get,
.parse = nftnl_expr_nat_parse,
.build = nftnl_expr_nat_build,
- .snprintf = nftnl_expr_nat_snprintf,
+ .output = nftnl_expr_nat_snprintf,
};
diff --git a/src/expr/numgen.c b/src/expr/numgen.c
index 4e0d541..c5e8772 100644
--- a/src/expr/numgen.c
+++ b/src/expr/numgen.c
@@ -143,11 +143,11 @@ nftnl_expr_ng_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_ng_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_ng_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_ng *ng = nftnl_expr_data(e);
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
switch (ng->type) {
case NFT_NG_INCREMENTAL:
@@ -172,28 +172,21 @@ nftnl_expr_ng_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_ng_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_ng_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy numgen_attr_policy[__NFTNL_EXPR_NG_MAX] = {
+ [NFTNL_EXPR_NG_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NG_MODULUS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NG_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_NG_OFFSET] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_ng = {
.name = "numgen",
.alloc_len = sizeof(struct nftnl_expr_ng),
- .max_attr = NFTA_NG_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_NG_MAX - 1,
+ .attr_policy = numgen_attr_policy,
.set = nftnl_expr_ng_set,
.get = nftnl_expr_ng_get,
.parse = nftnl_expr_ng_parse,
.build = nftnl_expr_ng_build,
- .snprintf = nftnl_expr_ng_snprintf,
+ .output = nftnl_expr_ng_snprintf,
};
diff --git a/src/expr/objref.c b/src/expr/objref.c
index 7388b18..59e1ddd 100644
--- a/src/expr/objref.c
+++ b/src/expr/objref.c
@@ -57,8 +57,6 @@ static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_OBJREF_SET_ID:
memcpy(&objref->set.id, data, sizeof(objref->set.id));
break;
- default:
- return -1;
}
return 0;
}
@@ -174,8 +172,9 @@ static int nftnl_expr_objref_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_objref_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int nftnl_expr_objref_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_expr *e)
{
struct nftnl_expr_objref *objref = nftnl_expr_data(e);
@@ -187,28 +186,31 @@ static int nftnl_expr_objref_snprintf_default(char *buf, size_t len,
objref->imm.type, objref->imm.name);
}
-static int nftnl_expr_objref_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_expr *e)
+static void nftnl_expr_objref_free(const struct nftnl_expr *e)
{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_objref_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ struct nftnl_expr_objref *objref = nftnl_expr_data(e);
+
+ xfree(objref->imm.name);
+ xfree(objref->set.name);
}
+static struct attr_policy objref_attr_policy[__NFTNL_EXPR_OBJREF_MAX] = {
+ [NFTNL_EXPR_OBJREF_IMM_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_OBJREF_IMM_NAME] = { .maxlen = NFT_NAME_MAXLEN },
+ [NFTNL_EXPR_OBJREF_SET_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_OBJREF_SET_NAME] = { .maxlen = NFT_NAME_MAXLEN },
+ [NFTNL_EXPR_OBJREF_SET_ID] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_objref = {
.name = "objref",
.alloc_len = sizeof(struct nftnl_expr_objref),
- .max_attr = NFTA_OBJREF_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_OBJREF_MAX - 1,
+ .attr_policy = objref_attr_policy,
+ .free = nftnl_expr_objref_free,
.set = nftnl_expr_objref_set,
.get = nftnl_expr_objref_get,
.parse = nftnl_expr_objref_parse,
.build = nftnl_expr_objref_build,
- .snprintf = nftnl_expr_objref_snprintf,
+ .output = nftnl_expr_objref_snprintf,
};
diff --git a/src/expr/osf.c b/src/expr/osf.c
index 98d0df9..1e4ceb0 100644
--- a/src/expr/osf.c
+++ b/src/expr/osf.c
@@ -124,11 +124,12 @@ nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_osf_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_osf_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_osf *osf = nftnl_expr_data(e);
- int ret, offset = 0, len = size;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_OSF_DREG)) {
ret = snprintf(buf, len, "dreg %u ", osf->dreg);
@@ -138,28 +139,20 @@ static int nftnl_expr_osf_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_osf_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_osf_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy osf_attr_policy[__NFTNL_EXPR_OSF_MAX] = {
+ [NFTNL_EXPR_OSF_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_OSF_TTL] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_EXPR_OSF_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_osf = {
.name = "osf",
.alloc_len = sizeof(struct nftnl_expr_osf),
- .max_attr = NFTA_OSF_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_OSF_MAX - 1,
+ .attr_policy = osf_attr_policy,
.set = nftnl_expr_osf_set,
.get = nftnl_expr_osf_get,
.parse = nftnl_expr_osf_parse,
.build = nftnl_expr_osf_build,
- .snprintf = nftnl_expr_osf_snprintf,
+ .output = nftnl_expr_osf_snprintf,
};
diff --git a/src/expr/payload.c b/src/expr/payload.c
index 2192dad..76d38f7 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -66,8 +66,6 @@ nftnl_expr_payload_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_PAYLOAD_FLAGS:
memcpy(&payload->csum_flags, data, sizeof(payload->csum_flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -203,68 +201,60 @@ nftnl_expr_payload_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static const char *base2str_array[NFT_PAYLOAD_TRANSPORT_HEADER+1] = {
+static const char *base2str_array[NFT_PAYLOAD_TUN_HEADER + 1] = {
[NFT_PAYLOAD_LL_HEADER] = "link",
[NFT_PAYLOAD_NETWORK_HEADER] = "network",
[NFT_PAYLOAD_TRANSPORT_HEADER] = "transport",
+ [NFT_PAYLOAD_INNER_HEADER] = "inner",
+ [NFT_PAYLOAD_TUN_HEADER] = "tunnel",
};
static const char *base2str(enum nft_payload_bases base)
{
- if (base > NFT_PAYLOAD_TRANSPORT_HEADER)
+ if (base > NFT_PAYLOAD_INNER_HEADER)
return "unknown";
return base2str_array[base];
}
-static inline int nftnl_str2base(const char *base)
-{
- if (strcmp(base, "link") == 0)
- return NFT_PAYLOAD_LL_HEADER;
- else if (strcmp(base, "network") == 0)
- return NFT_PAYLOAD_NETWORK_HEADER;
- else if (strcmp(base, "transport") == 0)
- return NFT_PAYLOAD_TRANSPORT_HEADER;
- else {
- errno = EINVAL;
- return -1;
- }
-}
-
static int
-nftnl_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
+nftnl_expr_payload_snprintf(char *buf, size_t len,
uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_payload *payload = nftnl_expr_data(e);
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- if (payload->sreg)
- return snprintf(buf, len, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ",
- payload->sreg,
- payload->len, base2str(payload->base),
- payload->offset, payload->csum_type,
- payload->csum_offset,
- payload->csum_flags);
- else
- return snprintf(buf, len, "load %ub @ %s header + %u => reg %u ",
- payload->len, base2str(payload->base),
- payload->offset, payload->dreg);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ if (payload->sreg)
+ return snprintf(buf, len, "write reg %u => %ub @ %s header + %u csum_type %u csum_off %u csum_flags 0x%x ",
+ payload->sreg,
+ payload->len, base2str(payload->base),
+ payload->offset, payload->csum_type,
+ payload->csum_offset,
+ payload->csum_flags);
+ else
+ return snprintf(buf, len, "load %ub @ %s header + %u => reg %u ",
+ payload->len, base2str(payload->base),
+ payload->offset, payload->dreg);
}
+static struct attr_policy payload_attr_policy[__NFTNL_EXPR_PAYLOAD_MAX] = {
+ [NFTNL_EXPR_PAYLOAD_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_BASE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_OFFSET] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_LEN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_CSUM_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_CSUM_OFFSET] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_PAYLOAD_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
+
struct expr_ops expr_ops_payload = {
.name = "payload",
.alloc_len = sizeof(struct nftnl_expr_payload),
- .max_attr = NFTA_PAYLOAD_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_PAYLOAD_MAX - 1,
+ .attr_policy = payload_attr_policy,
.set = nftnl_expr_payload_set,
.get = nftnl_expr_payload_get,
.parse = nftnl_expr_payload_parse,
.build = nftnl_expr_payload_build,
- .snprintf = nftnl_expr_payload_snprintf,
+ .output = nftnl_expr_payload_snprintf,
};
diff --git a/src/expr/queue.c b/src/expr/queue.c
index 051ef71..54792ef 100644
--- a/src/expr/queue.c
+++ b/src/expr/queue.c
@@ -45,8 +45,6 @@ static int nftnl_expr_queue_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_QUEUE_SREG_QNUM:
memcpy(&queue->sreg_qnum, data, sizeof(queue->sreg_qnum));
break;
- default:
- return -1;
}
return 0;
}
@@ -143,69 +141,63 @@ nftnl_expr_queue_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_queue_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_queue_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_queue *queue = nftnl_expr_data(e);
- int ret, remain = len, offset = 0;
uint16_t total_queues;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_QUEUE_NUM)) {
total_queues = queue->queuenum + queue->queues_total - 1;
- ret = snprintf(buf + offset, len, "num %u", queue->queuenum);
+ ret = snprintf(buf + offset, remain, "num %u", queue->queuenum);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (queue->queues_total && total_queues != queue->queuenum) {
- ret = snprintf(buf + offset, len, "-%u", total_queues);
+ ret = snprintf(buf + offset, remain, "-%u", total_queues);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- ret = snprintf(buf + offset, len, " ");
+ ret = snprintf(buf + offset, remain, " ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_EXPR_QUEUE_SREG_QNUM)) {
- ret = snprintf(buf + offset, len, "sreg_qnum %u ",
+ ret = snprintf(buf + offset, remain, "sreg_qnum %u ",
queue->sreg_qnum);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_EXPR_QUEUE_FLAGS)) {
if (queue->flags & (NFT_QUEUE_FLAG_BYPASS)) {
- ret = snprintf(buf + offset, len, "bypass ");
+ ret = snprintf(buf + offset, remain, "bypass ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (queue->flags & (NFT_QUEUE_FLAG_CPU_FANOUT)) {
- ret = snprintf(buf + offset, len, "fanout ");
+ ret = snprintf(buf + offset, remain, "fanout ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
}
return offset;
}
-static int
-nftnl_expr_queue_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_queue_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy queue_attr_policy[__NFTNL_EXPR_QUEUE_MAX] = {
+ [NFTNL_EXPR_QUEUE_NUM] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_QUEUE_TOTAL] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_QUEUE_FLAGS] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_QUEUE_SREG_QNUM] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_queue = {
.name = "queue",
.alloc_len = sizeof(struct nftnl_expr_queue),
- .max_attr = NFTA_QUEUE_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_QUEUE_MAX - 1,
+ .attr_policy = queue_attr_policy,
.set = nftnl_expr_queue_set,
.get = nftnl_expr_queue_get,
.parse = nftnl_expr_queue_parse,
.build = nftnl_expr_queue_build,
- .snprintf = nftnl_expr_queue_snprintf,
+ .output = nftnl_expr_queue_snprintf,
};
diff --git a/src/expr/quota.c b/src/expr/quota.c
index 39a92e6..60631fe 100644
--- a/src/expr/quota.c
+++ b/src/expr/quota.c
@@ -41,8 +41,6 @@ static int nftnl_expr_quota_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_QUOTA_FLAGS:
memcpy(&quota->flags, data, sizeof(quota->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -128,8 +126,9 @@ nftnl_expr_quota_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_quota_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int nftnl_expr_quota_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_expr *e)
{
struct nftnl_expr_quota *quota = nftnl_expr_data(e);
@@ -138,28 +137,20 @@ static int nftnl_expr_quota_snprintf_default(char *buf, size_t len,
quota->bytes, quota->consumed, quota->flags);
}
-static int nftnl_expr_quota_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_quota_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy quota_attr_policy[__NFTNL_EXPR_QUOTA_MAX] = {
+ [NFTNL_EXPR_QUOTA_BYTES] = { .maxlen = sizeof(uint64_t) },
+ [NFTNL_EXPR_QUOTA_FLAGS] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_QUOTA_CONSUMED] = { .maxlen = sizeof(uint64_t) },
+};
struct expr_ops expr_ops_quota = {
.name = "quota",
.alloc_len = sizeof(struct nftnl_expr_quota),
- .max_attr = NFTA_QUOTA_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_QUOTA_MAX - 1,
+ .attr_policy = quota_attr_policy,
.set = nftnl_expr_quota_set,
.get = nftnl_expr_quota_get,
.parse = nftnl_expr_quota_parse,
.build = nftnl_expr_quota_build,
- .snprintf = nftnl_expr_quota_snprintf,
+ .output = nftnl_expr_quota_snprintf,
};
diff --git a/src/expr/range.c b/src/expr/range.c
index d1d5083..6310b79 100644
--- a/src/expr/range.c
+++ b/src/expr/range.c
@@ -40,15 +40,9 @@ static int nftnl_expr_range_set(struct nftnl_expr *e, uint16_t type,
memcpy(&range->op, data, sizeof(range->op));
break;
case NFTNL_EXPR_RANGE_FROM_DATA:
- memcpy(&range->data_from.val, data, data_len);
- range->data_from.len = data_len;
- break;
+ return nftnl_data_cpy(&range->data_from, data, data_len);
case NFTNL_EXPR_RANGE_TO_DATA:
- memcpy(&range->data_to.val, data, data_len);
- range->data_to.len = data_len;
- break;
- default:
- return -1;
+ return nftnl_data_cpy(&range->data_to, data, data_len);
}
return 0;
}
@@ -184,48 +178,42 @@ static inline int nftnl_str2range(const char *op)
}
}
-static int nftnl_expr_range_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int nftnl_expr_range_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_range *range = nftnl_expr_data(e);
- int remain = size, offset = 0, ret;
+ int offset = 0, ret;
ret = snprintf(buf, remain, "%s reg %u ",
range2str(range->op), range->sreg);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_from,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_data_reg_snprintf(buf + offset, remain, &range->data_to,
- NFTNL_OUTPUT_DEFAULT, 0, DATA_VALUE);
+ 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
-static int nftnl_expr_range_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_range_snprintf_default(buf, size, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy range_attr_policy[__NFTNL_EXPR_RANGE_MAX] = {
+ [NFTNL_EXPR_RANGE_SREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_RANGE_OP] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_RANGE_FROM_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+ [NFTNL_EXPR_RANGE_TO_DATA] = { .maxlen = NFT_DATA_VALUE_MAXLEN },
+};
struct expr_ops expr_ops_range = {
.name = "range",
.alloc_len = sizeof(struct nftnl_expr_range),
- .max_attr = NFTA_RANGE_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_RANGE_MAX - 1,
+ .attr_policy = range_attr_policy,
.set = nftnl_expr_range_set,
.get = nftnl_expr_range_get,
.parse = nftnl_expr_range_parse,
.build = nftnl_expr_range_build,
- .snprintf = nftnl_expr_range_snprintf,
+ .output = nftnl_expr_range_snprintf,
};
diff --git a/src/expr/redir.c b/src/expr/redir.c
index 477659a..69095bd 100644
--- a/src/expr/redir.c
+++ b/src/expr/redir.c
@@ -42,8 +42,6 @@ nftnl_expr_redir_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_REDIR_FLAGS:
memcpy(&redir->flags, data, sizeof(redir->flags));
break;
- default:
- return -1;
}
return 0;
}
@@ -131,26 +129,27 @@ nftnl_expr_redir_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_redir_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_redir_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
- int ret, remain = len, offset = 0;
+ int ret, offset = 0;
struct nftnl_expr_redir *redir = nftnl_expr_data(e);
if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MIN)) {
- ret = snprintf(buf + offset, len, "proto_min reg %u ",
+ ret = snprintf(buf + offset, remain, "proto_min reg %u ",
redir->sreg_proto_min);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_REG_PROTO_MAX)) {
- ret = snprintf(buf + offset, len, "proto_max reg %u ",
+ ret = snprintf(buf + offset, remain, "proto_max reg %u ",
redir->sreg_proto_max);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (nftnl_expr_is_set(e, NFTNL_EXPR_REDIR_FLAGS)) {
- ret = snprintf(buf + offset, len, "flags 0x%x ",
+ ret = snprintf(buf + offset, remain, "flags 0x%x ",
redir->flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -158,28 +157,20 @@ static int nftnl_expr_redir_snprintf_default(char *buf, size_t len,
return offset;
}
-static int
-nftnl_expr_redir_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_redir_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy redir_attr_policy[__NFTNL_EXPR_REDIR_MAX] = {
+ [NFTNL_EXPR_REDIR_REG_PROTO_MIN] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_REDIR_REG_PROTO_MAX] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_REDIR_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_redir = {
.name = "redir",
.alloc_len = sizeof(struct nftnl_expr_redir),
- .max_attr = NFTA_REDIR_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_REDIR_MAX - 1,
+ .attr_policy = redir_attr_policy,
.set = nftnl_expr_redir_set,
.get = nftnl_expr_redir_get,
.parse = nftnl_expr_redir_parse,
.build = nftnl_expr_redir_build,
- .snprintf = nftnl_expr_redir_snprintf,
+ .output = nftnl_expr_redir_snprintf,
};
diff --git a/src/expr/reject.c b/src/expr/reject.c
index 141942e..f97011a 100644
--- a/src/expr/reject.c
+++ b/src/expr/reject.c
@@ -38,8 +38,6 @@ static int nftnl_expr_reject_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_REJECT_CODE:
memcpy(&reject->icmp_code, data, sizeof(reject->icmp_code));
break;
- default:
- return -1;
}
return 0;
}
@@ -116,8 +114,9 @@ nftnl_expr_reject_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_reject_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_reject_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_reject *reject = nftnl_expr_data(e);
@@ -125,28 +124,19 @@ static int nftnl_expr_reject_snprintf_default(char *buf, size_t len,
reject->type, reject->icmp_code);
}
-static int
-nftnl_expr_reject_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_reject_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy reject_attr_policy[__NFTNL_EXPR_REJECT_MAX] = {
+ [NFTNL_EXPR_REJECT_TYPE] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_REJECT_CODE] = { .maxlen = sizeof(uint8_t) },
+};
struct expr_ops expr_ops_reject = {
.name = "reject",
.alloc_len = sizeof(struct nftnl_expr_reject),
- .max_attr = NFTA_REJECT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_REJECT_MAX - 1,
+ .attr_policy = reject_attr_policy,
.set = nftnl_expr_reject_set,
.get = nftnl_expr_reject_get,
.parse = nftnl_expr_reject_parse,
.build = nftnl_expr_reject_build,
- .snprintf = nftnl_expr_reject_snprintf,
+ .output = nftnl_expr_reject_snprintf,
};
diff --git a/src/expr/rt.c b/src/expr/rt.c
index 0fce72d..0ab2556 100644
--- a/src/expr/rt.c
+++ b/src/expr/rt.c
@@ -37,8 +37,6 @@ nftnl_expr_rt_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_RT_DREG:
memcpy(&rt->dreg, data, sizeof(rt->dreg));
break;
- default:
- return -1;
}
return 0;
}
@@ -142,8 +140,8 @@ static inline int str2rt_key(const char *str)
}
static int
-nftnl_expr_rt_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+nftnl_expr_rt_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_rt *rt = nftnl_expr_data(e);
@@ -154,28 +152,19 @@ nftnl_expr_rt_snprintf_default(char *buf, size_t len,
return 0;
}
-static int
-nftnl_expr_rt_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_rt_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy rt_attr_policy[__NFTNL_EXPR_RT_MAX] = {
+ [NFTNL_EXPR_RT_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_RT_DREG] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_rt = {
.name = "rt",
.alloc_len = sizeof(struct nftnl_expr_rt),
- .max_attr = NFTA_RT_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_RT_MAX - 1,
+ .attr_policy = rt_attr_policy,
.set = nftnl_expr_rt_set,
.get = nftnl_expr_rt_get,
.parse = nftnl_expr_rt_parse,
.build = nftnl_expr_rt_build,
- .snprintf = nftnl_expr_rt_snprintf,
+ .output = nftnl_expr_rt_snprintf,
};
diff --git a/src/expr/socket.c b/src/expr/socket.c
index 96550d5..d0d8e23 100644
--- a/src/expr/socket.c
+++ b/src/expr/socket.c
@@ -22,6 +22,7 @@
struct nftnl_expr_socket {
enum nft_socket_keys key;
enum nft_registers dreg;
+ uint32_t level;
};
static int
@@ -37,8 +38,9 @@ nftnl_expr_socket_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_SOCKET_DREG:
memcpy(&socket->dreg, data, sizeof(socket->dreg));
break;
- default:
- return -1;
+ case NFTNL_EXPR_SOCKET_LEVEL:
+ memcpy(&socket->level, data, sizeof(socket->level));
+ break;
}
return 0;
}
@@ -56,6 +58,9 @@ nftnl_expr_socket_get(const struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_SOCKET_DREG:
*data_len = sizeof(socket->dreg);
return &socket->dreg;
+ case NFTNL_EXPR_SOCKET_LEVEL:
+ *data_len = sizeof(socket->level);
+ return &socket->level;
}
return NULL;
}
@@ -71,6 +76,7 @@ static int nftnl_expr_socket_cb(const struct nlattr *attr, void *data)
switch (type) {
case NFTA_SOCKET_KEY:
case NFTA_SOCKET_DREG:
+ case NFTA_SOCKET_LEVEL:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
@@ -89,6 +95,8 @@ nftnl_expr_socket_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
mnl_attr_put_u32(nlh, NFTA_SOCKET_KEY, htonl(socket->key));
if (e->flags & (1 << NFTNL_EXPR_SOCKET_DREG))
mnl_attr_put_u32(nlh, NFTA_SOCKET_DREG, htonl(socket->dreg));
+ if (e->flags & (1 << NFTNL_EXPR_SOCKET_LEVEL))
+ mnl_attr_put_u32(nlh, NFTA_SOCKET_LEVEL, htonl(socket->level));
}
static int
@@ -108,6 +116,10 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr)
socket->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_DREG]));
e->flags |= (1 << NFTNL_EXPR_SOCKET_DREG);
}
+ if (tb[NFTA_SOCKET_LEVEL]) {
+ socket->level = ntohl(mnl_attr_get_u32(tb[NFTA_SOCKET_LEVEL]));
+ e->flags |= (1 << NFTNL_EXPR_SOCKET_LEVEL);
+ }
return 0;
}
@@ -115,6 +127,8 @@ nftnl_expr_socket_parse(struct nftnl_expr *e, struct nlattr *attr)
static const char *socket_key2str_array[NFT_SOCKET_MAX + 1] = {
[NFT_SOCKET_TRANSPARENT] = "transparent",
[NFT_SOCKET_MARK] = "mark",
+ [NFT_SOCKET_WILDCARD] = "wildcard",
+ [NFT_SOCKET_CGROUPV2] = "cgroupv2",
};
static const char *socket_key2str(uint8_t key)
@@ -125,22 +139,9 @@ static const char *socket_key2str(uint8_t key)
return "unknown";
}
-static inline int str2socket_key(const char *str)
-{
- int i;
-
- for (i = 0; i < NFT_SOCKET_MAX + 1; i++) {
- if (strcmp(str, socket_key2str_array[i]) == 0)
- return i;
- }
-
- errno = EINVAL;
- return -1;
-}
-
static int
-nftnl_expr_socket_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+nftnl_expr_socket_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_socket *socket = nftnl_expr_data(e);
@@ -148,31 +149,26 @@ nftnl_expr_socket_snprintf_default(char *buf, size_t len,
return snprintf(buf, len, "load %s => reg %u ",
socket_key2str(socket->key), socket->dreg);
}
+ if (e->flags & (1 << NFTNL_EXPR_SOCKET_LEVEL))
+ return snprintf(buf, len, "level %u ", socket->level);
+
return 0;
}
-static int
-nftnl_expr_socket_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_socket_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy socket_attr_policy[__NFTNL_EXPR_SOCKET_MAX] = {
+ [NFTNL_EXPR_SOCKET_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_SOCKET_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_SOCKET_LEVEL] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_socket = {
.name = "socket",
.alloc_len = sizeof(struct nftnl_expr_socket),
- .max_attr = NFTA_SOCKET_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_SOCKET_MAX - 1,
+ .attr_policy = socket_attr_policy,
.set = nftnl_expr_socket_set,
.get = nftnl_expr_socket_get,
.parse = nftnl_expr_socket_parse,
.build = nftnl_expr_socket_build,
- .snprintf = nftnl_expr_socket_snprintf,
+ .output = nftnl_expr_socket_snprintf,
};
diff --git a/src/expr/synproxy.c b/src/expr/synproxy.c
index 245f4fb..898d292 100644
--- a/src/expr/synproxy.c
+++ b/src/expr/synproxy.c
@@ -127,11 +127,12 @@ nftnl_expr_synproxy_parse(struct nftnl_expr *e, struct nlattr *attr)
return 0;
}
-static int nftnl_expr_synproxy_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+static int
+nftnl_expr_synproxy_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_synproxy *synproxy = nftnl_expr_data(e);
- int ret, offset = 0, len = size;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_SYNPROXY_MSS) &&
e->flags & (1 << NFTNL_EXPR_SYNPROXY_WSCALE)) {
@@ -143,28 +144,20 @@ static int nftnl_expr_synproxy_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_synproxy_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_synproxy_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy synproxy_attr_policy[__NFTNL_EXPR_SYNPROXY_MAX] = {
+ [NFTNL_EXPR_SYNPROXY_MSS] = { .maxlen = sizeof(uint16_t) },
+ [NFTNL_EXPR_SYNPROXY_WSCALE] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_EXPR_SYNPROXY_FLAGS] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_synproxy = {
.name = "synproxy",
.alloc_len = sizeof(struct nftnl_expr_synproxy),
- .max_attr = NFTA_SYNPROXY_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_SYNPROXY_MAX - 1,
+ .attr_policy = synproxy_attr_policy,
.set = nftnl_expr_synproxy_set,
.get = nftnl_expr_synproxy_get,
.parse = nftnl_expr_synproxy_parse,
.build = nftnl_expr_synproxy_build,
- .snprintf = nftnl_expr_synproxy_snprintf,
+ .output = nftnl_expr_synproxy_snprintf,
};
diff --git a/src/expr/target.c b/src/expr/target.c
index 9100038..9bfd25b 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -55,8 +55,6 @@ nftnl_expr_target_set(struct nftnl_expr *e, uint16_t type,
tg->data = data;
tg->data_len = data_len;
break;
- default:
- return -1;
}
return 0;
}
@@ -165,21 +163,12 @@ static int nftnl_expr_target_parse(struct nftnl_expr *e, struct nlattr *attr)
}
static int
-nftnl_expr_target_snprintf(char *buf, size_t len, uint32_t type,
+nftnl_expr_target_snprintf(char *buf, size_t len,
uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_target *target = nftnl_expr_data(e);
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return snprintf(buf, len, "name %s rev %u ",
- target->name, target->rev);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ return snprintf(buf, len, "name %s rev %u ", target->name, target->rev);
}
static void nftnl_expr_target_free(const struct nftnl_expr *e)
@@ -189,14 +178,21 @@ static void nftnl_expr_target_free(const struct nftnl_expr *e)
xfree(target->data);
}
+static struct attr_policy target_attr_policy[__NFTNL_EXPR_TG_MAX] = {
+ [NFTNL_EXPR_TG_NAME] = { .maxlen = XT_EXTENSION_MAXNAMELEN },
+ [NFTNL_EXPR_TG_REV] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_TG_INFO] = { .maxlen = 0 },
+};
+
struct expr_ops expr_ops_target = {
.name = "target",
.alloc_len = sizeof(struct nftnl_expr_target),
- .max_attr = NFTA_TARGET_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_TG_MAX - 1,
+ .attr_policy = target_attr_policy,
.free = nftnl_expr_target_free,
.set = nftnl_expr_target_set,
.get = nftnl_expr_target_get,
.parse = nftnl_expr_target_parse,
.build = nftnl_expr_target_build,
- .snprintf = nftnl_expr_target_snprintf,
+ .output = nftnl_expr_target_snprintf,
};
diff --git a/src/expr/tproxy.c b/src/expr/tproxy.c
index 3827b75..4948392 100644
--- a/src/expr/tproxy.c
+++ b/src/expr/tproxy.c
@@ -42,8 +42,6 @@ nftnl_expr_tproxy_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_TPROXY_REG_PORT:
memcpy(&tproxy->sreg_port, data, sizeof(tproxy->sreg_port));
break;
- default:
- return -1;
}
return 0;
@@ -135,11 +133,11 @@ nftnl_expr_tproxy_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
}
static int
-nftnl_expr_tproxy_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_tproxy_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_tproxy *tproxy = nftnl_expr_data(e);
- int remain = size, offset = 0, ret = 0;
+ int offset = 0, ret = 0;
if (tproxy->family != NFTA_TPROXY_UNSPEC) {
ret = snprintf(buf + offset, remain, "%s ",
@@ -162,26 +160,20 @@ nftnl_expr_tproxy_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_tproxy_snprintf(char *buf, size_t size, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_tproxy_snprintf_default(buf, size, e);
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy tproxy_attr_policy[__NFTNL_EXPR_TPROXY_MAX] = {
+ [NFTNL_EXPR_TPROXY_FAMILY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_TPROXY_REG_ADDR] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_TPROXY_REG_PORT] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_tproxy = {
.name = "tproxy",
.alloc_len = sizeof(struct nftnl_expr_tproxy),
- .max_attr = NFTA_TPROXY_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_TPROXY_MAX - 1,
+ .attr_policy = tproxy_attr_policy,
.set = nftnl_expr_tproxy_set,
.get = nftnl_expr_tproxy_get,
.parse = nftnl_expr_tproxy_parse,
.build = nftnl_expr_tproxy_build,
- .snprintf = nftnl_expr_tproxy_snprintf,
+ .output = nftnl_expr_tproxy_snprintf,
};
diff --git a/src/expr/tunnel.c b/src/expr/tunnel.c
index b2b8d72..8089d0b 100644
--- a/src/expr/tunnel.c
+++ b/src/expr/tunnel.c
@@ -36,8 +36,6 @@ static int nftnl_expr_tunnel_set(struct nftnl_expr *e, uint16_t type,
case NFTNL_EXPR_TUNNEL_DREG:
memcpy(&tunnel->dreg, data, sizeof(tunnel->dreg));
break;
- default:
- return -1;
}
return 0;
}
@@ -124,22 +122,9 @@ static const char *tunnel_key2str(uint8_t key)
return "unknown";
}
-static inline int str2tunnel_key(const char *str)
-{
- int i;
-
- for (i = 0; i <= NFT_TUNNEL_MAX; i++) {
- if (strcmp(str, tunnel_key2str_array[i]) == 0)
- return i;
- }
-
- errno = EINVAL;
- return -1;
-}
-
static int
-nftnl_expr_tunnel_snprintf_default(char *buf, size_t len,
- const struct nftnl_expr *e)
+nftnl_expr_tunnel_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
@@ -150,28 +135,19 @@ nftnl_expr_tunnel_snprintf_default(char *buf, size_t len,
return 0;
}
-static int
-nftnl_expr_tunnel_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_tunnel_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy tunnel_attr_policy[__NFTNL_EXPR_TUNNEL_MAX] = {
+ [NFTNL_EXPR_TUNNEL_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_TUNNEL_DREG] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_tunnel = {
.name = "tunnel",
.alloc_len = sizeof(struct nftnl_expr_tunnel),
- .max_attr = NFTA_TUNNEL_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_TUNNEL_MAX - 1,
+ .attr_policy = tunnel_attr_policy,
.set = nftnl_expr_tunnel_set,
.get = nftnl_expr_tunnel_get,
.parse = nftnl_expr_tunnel_parse,
.build = nftnl_expr_tunnel_build,
- .snprintf = nftnl_expr_tunnel_snprintf,
+ .output = nftnl_expr_tunnel_snprintf,
};
diff --git a/src/expr/xfrm.c b/src/expr/xfrm.c
index 8fe5438..dc867a2 100644
--- a/src/expr/xfrm.c
+++ b/src/expr/xfrm.c
@@ -171,40 +171,12 @@ static const char *xfrmdir2str(uint8_t dir)
return xfrmdir2str_array[dir];
}
-#ifdef JSON_PARSING
-static uint32_t str2xfrmkey(const char *s)
-{
- int i;
-
- for (i = 0;
- i < sizeof(xfrmkey2str_array) / sizeof(xfrmkey2str_array[0]);
- i++) {
- if (strcmp(xfrmkey2str_array[i], s) == 0)
- return i;
- }
- return -1;
-}
-
-static int str2xfmrdir(const char *s)
-{
- int i;
-
- for (i = 0;
- i < sizeof(xfrmdir2str_array) / sizeof(xfrmdir2str_array[0]);
- i++) {
- if (strcmp(xfrmkey2str_array[i], s) == 0)
- return i;
- }
- return -1;
-}
-#endif
-
static int
-nftnl_expr_xfrm_snprintf_default(char *buf, size_t size,
- const struct nftnl_expr *e)
+nftnl_expr_xfrm_snprintf(char *buf, size_t remain,
+ uint32_t flags, const struct nftnl_expr *e)
{
struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
- int ret, remain = size, offset = 0;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_EXPR_XFRM_DREG)) {
ret = snprintf(buf, remain, "load %s %u %s => reg %u ",
@@ -216,28 +188,22 @@ nftnl_expr_xfrm_snprintf_default(char *buf, size_t size,
return offset;
}
-static int
-nftnl_expr_xfrm_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_expr *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_expr_xfrm_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
+static struct attr_policy xfrm_attr_policy[__NFTNL_EXPR_XFRM_MAX] = {
+ [NFTNL_EXPR_XFRM_DREG] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_XFRM_SREG] = { .maxlen = 0 },
+ [NFTNL_EXPR_XFRM_KEY] = { .maxlen = sizeof(uint32_t) },
+ [NFTNL_EXPR_XFRM_DIR] = { .maxlen = sizeof(uint8_t) },
+ [NFTNL_EXPR_XFRM_SPNUM] = { .maxlen = sizeof(uint32_t) },
+};
struct expr_ops expr_ops_xfrm = {
.name = "xfrm",
.alloc_len = sizeof(struct nftnl_expr_xfrm),
- .max_attr = NFTA_XFRM_MAX,
+ .nftnl_max_attr = __NFTNL_EXPR_XFRM_MAX - 1,
+ .attr_policy = xfrm_attr_policy,
.set = nftnl_expr_xfrm_set,
.get = nftnl_expr_xfrm_get,
.parse = nftnl_expr_xfrm_parse,
.build = nftnl_expr_xfrm_build,
- .snprintf = nftnl_expr_xfrm_snprintf,
+ .output = nftnl_expr_xfrm_snprintf,
};
diff --git a/src/expr_ops.c b/src/expr_ops.c
index 3538dd6..b85f472 100644
--- a/src/expr_ops.c
+++ b/src/expr_ops.c
@@ -14,6 +14,8 @@ extern struct expr_ops expr_ops_dup;
extern struct expr_ops expr_ops_exthdr;
extern struct expr_ops expr_ops_fwd;
extern struct expr_ops expr_ops_immediate;
+extern struct expr_ops expr_ops_inner;
+extern struct expr_ops expr_ops_last;
extern struct expr_ops expr_ops_limit;
extern struct expr_ops expr_ops_log;
extern struct expr_ops expr_ops_lookup;
@@ -57,6 +59,8 @@ static struct expr_ops *expr_ops[] = {
&expr_ops_exthdr,
&expr_ops_fwd,
&expr_ops_immediate,
+ &expr_ops_inner,
+ &expr_ops_last,
&expr_ops_limit,
&expr_ops_log,
&expr_ops_lookup,
diff --git a/src/flowtable.c b/src/flowtable.c
index 1e235d0..e6c2475 100644
--- a/src/flowtable.c
+++ b/src/flowtable.c
@@ -206,6 +206,13 @@ void nftnl_flowtable_set_u64(struct nftnl_flowtable *c, uint16_t attr, uint64_t
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)
@@ -230,6 +237,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);
@@ -290,35 +298,53 @@ int32_t nftnl_flowtable_get_s32(const struct nftnl_flowtable *c, uint16_t attr)
return val ? *val : 0;
}
+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))
@@ -565,10 +591,10 @@ int nftnl_flowtable_parse_file(struct nftnl_flowtable *c,
return -1;
}
-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);
@@ -597,25 +623,18 @@ 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;
}
diff --git a/src/gen.c b/src/gen.c
index f2ac2ba..88efbaa 100644
--- a/src/gen.c
+++ b/src/gen.c
@@ -156,21 +156,17 @@ int nftnl_gen_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_gen *gen)
return 0;
}
-static int nftnl_gen_cmd_snprintf(char *buf, size_t size,
+static int nftnl_gen_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_gen *gen, 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 = snprintf(buf, size, "ruleset generation ID %u", gen->id);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
+ ret = snprintf(buf, remain, "ruleset generation ID %u", gen->id);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/libnftnl.map b/src/libnftnl.map
index 5ba8d99..8fffff1 100644
--- a/src/libnftnl.map
+++ b/src/libnftnl.map
@@ -47,8 +47,6 @@ global:
nftnl_chain_get_s32;
nftnl_chain_get_u64;
nftnl_chain_get_str;
- nftnl_chain_parse;
- nftnl_chain_parse_file;
nftnl_chain_snprintf;
nftnl_chain_fprintf;
nftnl_chain_nlmsg_build_payload;
@@ -169,13 +167,11 @@ global:
nftnl_set_elem_parse;
nftnl_set_elem_parse_file;
nftnl_set_elem_snprintf;
- nftnl_set_elem_fprinf;
+ nftnl_set_elem_fprintf;
nftnl_set_elems_nlmsg_build_payload;
nftnl_set_elems_nlmsg_parse;
- nftnl_set_elems_foreach;
-
nftnl_set_elems_iter_create;
nftnl_set_elems_iter_cur;
nftnl_set_elems_iter_next;
@@ -363,4 +359,27 @@ LIBNFTNL_13 {
LIBNFTNL_14 {
nftnl_udata_nest_start;
nftnl_udata_nest_end;
+ nftnl_chain_set_array;
+ nftnl_chain_get_array;
+ nftnl_flowtable_set_array;
+ nftnl_flowtable_get_array;
} LIBNFTNL_13;
+
+LIBNFTNL_15 {
+ nftnl_obj_get_data;
+ nftnl_expr_build_payload;
+ nftnl_rule_del_expr;
+} LIBNFTNL_14;
+
+LIBNFTNL_16 {
+ nftnl_set_add_expr;
+ nftnl_set_expr_foreach;
+ nftnl_set_elem_add_expr;
+ nftnl_set_elem_expr_foreach;
+ nftnl_expr_add_expr;
+ nftnl_expr_expr_foreach;
+} LIBNFTNL_15;
+
+LIBNFTNL_17 {
+ nftnl_set_elem_nlmsg_build;
+} LIBNFTNL_16;
diff --git a/src/obj/counter.c b/src/obj/counter.c
index 1baba4e..ebf3e74 100644
--- a/src/obj/counter.c
+++ b/src/obj/counter.c
@@ -109,8 +109,8 @@ nftnl_obj_counter_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_counter_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
@@ -118,24 +118,6 @@ static int nftnl_obj_counter_snprintf_default(char *buf, size_t len,
ctr->pkts, ctr->bytes);
}
-static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_counter_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_counter = {
.name = "counter",
.type = NFT_OBJECT_COUNTER,
@@ -145,5 +127,5 @@ struct obj_ops obj_ops_counter = {
.get = nftnl_obj_counter_get,
.parse = nftnl_obj_counter_parse,
.build = nftnl_obj_counter_build,
- .snprintf = nftnl_obj_counter_snprintf,
+ .output = nftnl_obj_counter_snprintf,
};
diff --git a/src/obj/ct_expect.c b/src/obj/ct_expect.c
index c0bb5ba..810ba9a 100644
--- a/src/obj/ct_expect.c
+++ b/src/obj/ct_expect.c
@@ -151,31 +151,35 @@ nftnl_obj_ct_expect_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_expect_snprintf(char *buf, size_t remain,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
- int ret = 0;
- int offset = 0, remain = len;
struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
+ int ret = 0, offset = 0;
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) {
- ret = snprintf(buf + offset, len, "family %d ", exp->l3proto);
+ ret = snprintf(buf + offset, remain,
+ "family %d ", exp->l3proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) {
- ret = snprintf(buf + offset, len, "protocol %d ", exp->l4proto);
+ ret = snprintf(buf + offset, remain,
+ "protocol %d ", exp->l4proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT)) {
- ret = snprintf(buf + offset, len, "dport %d ", exp->dport);
+ ret = snprintf(buf + offset, remain,
+ "dport %d ", exp->dport);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) {
- ret = snprintf(buf + offset, len, "timeout %d ", exp->timeout);
+ ret = snprintf(buf + offset, remain,
+ "timeout %d ", exp->timeout);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE)) {
- ret = snprintf(buf + offset, len, "size %d ", exp->size);
+ ret = snprintf(buf + offset, remain, "size %d ", exp->size);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -183,23 +187,6 @@ static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
return offset;
}
-static int nftnl_obj_ct_expect_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_expect_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_ct_expect = {
.name = "ct_expect",
.type = NFT_OBJECT_CT_EXPECT,
@@ -209,5 +196,5 @@ struct obj_ops obj_ops_ct_expect = {
.get = nftnl_obj_ct_expect_get,
.parse = nftnl_obj_ct_expect_parse,
.build = nftnl_obj_ct_expect_build,
- .snprintf = nftnl_obj_ct_expect_snprintf,
+ .output = nftnl_obj_ct_expect_snprintf,
};
diff --git a/src/obj/ct_helper.c b/src/obj/ct_helper.c
index d91f636..a31bd6f 100644
--- a/src/obj/ct_helper.c
+++ b/src/obj/ct_helper.c
@@ -131,8 +131,9 @@ nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
@@ -140,23 +141,6 @@ static int nftnl_obj_ct_helper_snprintf_default(char *buf, size_t len,
helper->name, helper->l3proto, helper->l4proto);
}
-static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_helper_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_ct_helper = {
.name = "ct_helper",
.type = NFT_OBJECT_CT_HELPER,
@@ -166,5 +150,5 @@ struct obj_ops obj_ops_ct_helper = {
.get = nftnl_obj_ct_helper_get,
.parse = nftnl_obj_ct_helper_parse,
.build = nftnl_obj_ct_helper_build,
- .snprintf = nftnl_obj_ct_helper_snprintf,
+ .output = nftnl_obj_ct_helper_snprintf,
};
diff --git a/src/obj/ct_timeout.c b/src/obj/ct_timeout.c
index 2662cac..fedf9e3 100644
--- a/src/obj/ct_timeout.c
+++ b/src/obj/ct_timeout.c
@@ -21,7 +21,7 @@
#include "obj.h"
-static const char *const tcp_state_to_name[] = {
+static const char *const tcp_state_to_name[NFTNL_CTTIMEOUT_TCP_MAX] = {
[NFTNL_CTTIMEOUT_TCP_SYN_SENT] = "SYN_SENT",
[NFTNL_CTTIMEOUT_TCP_SYN_RECV] = "SYN_RECV",
[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = "ESTABLISHED",
@@ -35,7 +35,7 @@ static const char *const tcp_state_to_name[] = {
[NFTNL_CTTIMEOUT_TCP_UNACK] = "UNACKNOWLEDGED",
};
-static uint32_t tcp_dflt_timeout[] = {
+static uint32_t tcp_dflt_timeout[NFTNL_CTTIMEOUT_TCP_MAX] = {
[NFTNL_CTTIMEOUT_TCP_SYN_SENT] = 120,
[NFTNL_CTTIMEOUT_TCP_SYN_RECV] = 60,
[NFTNL_CTTIMEOUT_TCP_ESTABLISHED] = 432000,
@@ -49,12 +49,12 @@ static uint32_t tcp_dflt_timeout[] = {
[NFTNL_CTTIMEOUT_TCP_UNACK] = 300,
};
-static const char *const udp_state_to_name[] = {
+static const char *const udp_state_to_name[NFTNL_CTTIMEOUT_UDP_MAX] = {
[NFTNL_CTTIMEOUT_UDP_UNREPLIED] = "UNREPLIED",
[NFTNL_CTTIMEOUT_UDP_REPLIED] = "REPLIED",
};
-static uint32_t udp_dflt_timeout[] = {
+static uint32_t udp_dflt_timeout[NFTNL_CTTIMEOUT_UDP_MAX] = {
[NFTNL_CTTIMEOUT_UDP_UNREPLIED] = 30,
[NFTNL_CTTIMEOUT_UDP_REPLIED] = 180,
};
@@ -156,6 +156,9 @@ static int nftnl_obj_ct_timeout_set(struct nftnl_obj *e, uint16_t type,
memcpy(&timeout->l4proto, data, sizeof(timeout->l4proto));
break;
case NFTNL_OBJ_CT_TIMEOUT_ARRAY:
+ if (data_len < sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX)
+ return -1;
+
memcpy(timeout->timeout, data,
sizeof(uint32_t) * NFTNL_CTTIMEOUT_ARRAY_MAX);
break;
@@ -257,21 +260,21 @@ nftnl_obj_ct_timeout_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t remain,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
- int ret = 0;
- int offset = 0, remain = len;
+ int ret = 0, offset = 0;
struct nftnl_obj_ct_timeout *timeout = nftnl_obj_data(e);
if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L3PROTO)) {
- ret = snprintf(buf + offset, len, "family %d ",
+ ret = snprintf(buf + offset, remain, "family %d ",
timeout->l3proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
if (e->flags & (1 << NFTNL_OBJ_CT_TIMEOUT_L4PROTO)) {
- ret = snprintf(buf + offset, len, "protocol %d ",
+ ret = snprintf(buf + offset, remain, "protocol %d ",
timeout->l4proto);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -283,7 +286,7 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
if (timeout_protocol[timeout->l4proto].attr_max == 0)
l4num = IPPROTO_RAW;
- ret = snprintf(buf + offset, len, "policy = {");
+ ret = snprintf(buf + offset, remain, "policy = {");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
for (i = 0; i < timeout_protocol[l4num].attr_max; i++) {
@@ -293,13 +296,13 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
"UNKNOWN";
if (timeout->timeout[i] != timeout_protocol[l4num].dflt_timeout[i]) {
- ret = snprintf(buf + offset, len,
+ ret = snprintf(buf + offset, remain,
"%s = %u,", state_name, timeout->timeout[i]);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
}
- ret = snprintf(buf + offset, len, "}");
+ ret = snprintf(buf + offset, remain, "}");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
buf[offset] = '\0';
@@ -307,23 +310,6 @@ static int nftnl_obj_ct_timeout_snprintf_default(char *buf, size_t len,
return offset;
}
-static int nftnl_obj_ct_timeout_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_ct_timeout_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_ct_timeout = {
.name = "ct_timeout",
.type = NFT_OBJECT_CT_TIMEOUT,
@@ -333,5 +319,5 @@ struct obj_ops obj_ops_ct_timeout = {
.get = nftnl_obj_ct_timeout_get,
.parse = nftnl_obj_ct_timeout_parse,
.build = nftnl_obj_ct_timeout_build,
- .snprintf = nftnl_obj_ct_timeout_snprintf,
+ .output = nftnl_obj_ct_timeout_snprintf,
};
diff --git a/src/obj/limit.c b/src/obj/limit.c
index 60b0159..d7b1aed 100644
--- a/src/obj/limit.c
+++ b/src/obj/limit.c
@@ -148,8 +148,9 @@ static int nftnl_obj_limit_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_limit_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_limit_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_limit *limit = nftnl_obj_data(e);
@@ -158,24 +159,6 @@ static int nftnl_obj_limit_snprintf_default(char *buf, size_t len,
limit->burst, limit->type, limit->flags);
}
-static int nftnl_obj_limit_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_limit_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_limit = {
.name = "limit",
.type = NFT_OBJECT_LIMIT,
@@ -185,5 +168,5 @@ struct obj_ops obj_ops_limit = {
.get = nftnl_obj_limit_get,
.parse = nftnl_obj_limit_parse,
.build = nftnl_obj_limit_build,
- .snprintf = nftnl_obj_limit_snprintf,
+ .output = nftnl_obj_limit_snprintf,
};
diff --git a/src/obj/quota.c b/src/obj/quota.c
index 1914037..6c7559a 100644
--- a/src/obj/quota.c
+++ b/src/obj/quota.c
@@ -125,8 +125,9 @@ nftnl_obj_quota_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_quota_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_quota_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_quota *quota = nftnl_obj_data(e);
@@ -134,24 +135,6 @@ static int nftnl_obj_quota_snprintf_default(char *buf, size_t len,
quota->bytes, quota->flags);
}
-static int nftnl_obj_quota_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_quota_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_quota = {
.name = "quota",
.type = NFT_OBJECT_QUOTA,
@@ -161,5 +144,5 @@ struct obj_ops obj_ops_quota = {
.get = nftnl_obj_quota_get,
.parse = nftnl_obj_quota_parse,
.build = nftnl_obj_quota_build,
- .snprintf = nftnl_obj_quota_snprintf,
+ .output = nftnl_obj_quota_snprintf,
};
diff --git a/src/obj/secmark.c b/src/obj/secmark.c
index e27b5fa..e5c24b3 100644
--- a/src/obj/secmark.c
+++ b/src/obj/secmark.c
@@ -98,30 +98,13 @@ nftnl_obj_secmark_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_secmark_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
-{
- struct nftnl_obj_secmark *secmark = nftnl_obj_data(e);
-
- return snprintf(buf, len, "context %s ", secmark->ctx);
-}
-
-static int nftnl_obj_secmark_snprintf(char *buf, size_t len, uint32_t type,
+static int nftnl_obj_secmark_snprintf(char *buf, size_t len,
uint32_t flags,
const struct nftnl_obj *e)
{
- if (len)
- buf[0] = '\0';
+ struct nftnl_obj_secmark *secmark = nftnl_obj_data(e);
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_secmark_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
+ return snprintf(buf, len, "context %s ", secmark->ctx);
}
struct obj_ops obj_ops_secmark = {
@@ -133,5 +116,5 @@ struct obj_ops obj_ops_secmark = {
.get = nftnl_obj_secmark_get,
.parse = nftnl_obj_secmark_parse,
.build = nftnl_obj_secmark_build,
- .snprintf = nftnl_obj_secmark_snprintf,
+ .output = nftnl_obj_secmark_snprintf,
};
diff --git a/src/obj/synproxy.c b/src/obj/synproxy.c
index 56ebc85..baef5c2 100644
--- a/src/obj/synproxy.c
+++ b/src/obj/synproxy.c
@@ -117,11 +117,12 @@ static int nftnl_obj_synproxy_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size,
- const struct nftnl_obj *e)
+static int nftnl_obj_synproxy_snprintf(char *buf, size_t len,
+ uint32_t flags,
+ const struct nftnl_obj *e)
{
struct nftnl_obj_synproxy *synproxy = nftnl_obj_data(e);
- int ret, offset = 0, len = size;
+ int ret, offset = 0;
if (e->flags & (1 << NFTNL_OBJ_SYNPROXY_MSS) &&
e->flags & (1 << NFTNL_OBJ_SYNPROXY_WSCALE)) {
@@ -133,21 +134,6 @@ static int nftnl_obj_synproxy_snprintf_default(char *buf, size_t size,
return offset;
}
-static int nftnl_obj_synproxy_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags,
- const struct nftnl_obj *e)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_synproxy_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_synproxy = {
.name = "synproxy",
.type = NFT_OBJECT_SYNPROXY,
@@ -157,5 +143,5 @@ struct obj_ops obj_ops_synproxy = {
.get = nftnl_obj_synproxy_get,
.parse = nftnl_obj_synproxy_parse,
.build = nftnl_obj_synproxy_build,
- .snprintf = nftnl_obj_synproxy_snprintf,
+ .output = nftnl_obj_synproxy_snprintf,
};
diff --git a/src/obj/tunnel.c b/src/obj/tunnel.c
index 100aa09..d2503dc 100644
--- a/src/obj/tunnel.c
+++ b/src/obj/tunnel.c
@@ -530,31 +530,14 @@ nftnl_obj_tunnel_parse(struct nftnl_obj *e, struct nlattr *attr)
return 0;
}
-static int nftnl_obj_tunnel_snprintf_default(char *buf, size_t len,
- const struct nftnl_obj *e)
+static int nftnl_obj_tunnel_snprintf(char *buf, size_t len,
+ uint32_t flags, const struct nftnl_obj *e)
{
struct nftnl_obj_tunnel *tun = nftnl_obj_data(e);
return snprintf(buf, len, "id %u ", tun->id);
}
-static int nftnl_obj_tunnel_snprintf(char *buf, size_t len, uint32_t type,
- uint32_t flags, const struct nftnl_obj *e)
-{
- if (len)
- buf[0] = '\0';
-
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- return nftnl_obj_tunnel_snprintf_default(buf, len, e);
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
- break;
- }
- return -1;
-}
-
struct obj_ops obj_ops_tunnel = {
.name = "tunnel",
.type = NFT_OBJECT_TUNNEL,
@@ -564,5 +547,5 @@ struct obj_ops obj_ops_tunnel = {
.get = nftnl_obj_tunnel_get,
.parse = nftnl_obj_tunnel_parse,
.build = nftnl_obj_tunnel_build,
- .snprintf = nftnl_obj_tunnel_snprintf,
+ .output = nftnl_obj_tunnel_snprintf,
};
diff --git a/src/object.c b/src/object.c
index 4f58272..0814be7 100644
--- a/src/object.c
+++ b/src/object.c
@@ -57,6 +57,8 @@ void nftnl_obj_free(const struct nftnl_obj *obj)
xfree(obj->table);
if (obj->flags & (1 << NFTNL_OBJ_NAME))
xfree(obj->name);
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ xfree(obj->user.data);
xfree(obj);
}
@@ -67,6 +69,34 @@ bool nftnl_obj_is_set(const struct nftnl_obj *obj, uint16_t attr)
return obj->flags & (1 << attr);
}
+EXPORT_SYMBOL(nftnl_obj_unset);
+void nftnl_obj_unset(struct nftnl_obj *obj, uint16_t attr)
+{
+ if (!(obj->flags & (1 << attr)))
+ return;
+
+ switch (attr) {
+ case NFTNL_OBJ_TABLE:
+ xfree(obj->table);
+ break;
+ case NFTNL_OBJ_NAME:
+ xfree(obj->name);
+ break;
+ case NFTNL_OBJ_USERDATA:
+ xfree(obj->user.data);
+ break;
+ case NFTNL_OBJ_TYPE:
+ case NFTNL_OBJ_FAMILY:
+ case NFTNL_OBJ_USE:
+ case NFTNL_OBJ_HANDLE:
+ break;
+ default:
+ break;
+ }
+
+ obj->flags &= ~(1 << attr);
+}
+
static uint32_t nftnl_obj_validate[NFTNL_OBJ_MAX + 1] = {
[NFTNL_OBJ_FAMILY] = sizeof(uint32_t),
[NFTNL_OBJ_USE] = sizeof(uint32_t),
@@ -103,6 +133,16 @@ void nftnl_obj_set_data(struct nftnl_obj *obj, uint16_t attr,
case NFTNL_OBJ_HANDLE:
memcpy(&obj->handle, data, sizeof(obj->handle));
break;
+ case NFTNL_OBJ_USERDATA:
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ xfree(obj->user.data);
+
+ obj->user.data = malloc(data_len);
+ if (!obj->user.data)
+ return;
+ memcpy(obj->user.data, data, data_len);
+ obj->user.len = data_len;
+ break;
default:
if (obj->ops)
obj->ops->set(obj, attr, data, data_len);
@@ -148,7 +188,7 @@ void nftnl_obj_set_str(struct nftnl_obj *obj, uint16_t attr, const char *str)
}
EXPORT_SYMBOL(nftnl_obj_get_data);
-const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr,
+const void *nftnl_obj_get_data(const struct nftnl_obj *obj, uint16_t attr,
uint32_t *data_len)
{
if (!(obj->flags & (1 << attr)))
@@ -174,6 +214,9 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr,
case NFTNL_OBJ_HANDLE:
*data_len = sizeof(uint64_t);
return &obj->handle;
+ case NFTNL_OBJ_USERDATA:
+ *data_len = obj->user.len;
+ return obj->user.data;
default:
if (obj->ops)
return obj->ops->get(obj, attr, data_len);
@@ -183,42 +226,42 @@ const void *nftnl_obj_get_data(struct nftnl_obj *obj, uint16_t attr,
}
EXPORT_SYMBOL(nftnl_obj_get);
-const void *nftnl_obj_get(struct nftnl_obj *obj, uint16_t attr)
+const void *nftnl_obj_get(const struct nftnl_obj *obj, uint16_t attr)
{
uint32_t data_len;
return nftnl_obj_get_data(obj, attr, &data_len);
}
EXPORT_SYMBOL(nftnl_obj_get_u8);
-uint8_t nftnl_obj_get_u8(struct nftnl_obj *obj, uint16_t attr)
+uint8_t nftnl_obj_get_u8(const struct nftnl_obj *obj, uint16_t attr)
{
const void *ret = nftnl_obj_get(obj, attr);
return ret == NULL ? 0 : *((uint8_t *)ret);
}
EXPORT_SYMBOL(nftnl_obj_get_u16);
-uint16_t nftnl_obj_get_u16(struct nftnl_obj *obj, uint16_t attr)
+uint16_t nftnl_obj_get_u16(const struct nftnl_obj *obj, uint16_t attr)
{
const void *ret = nftnl_obj_get(obj, attr);
return ret == NULL ? 0 : *((uint16_t *)ret);
}
EXPORT_SYMBOL(nftnl_obj_get_u32);
-uint32_t nftnl_obj_get_u32(struct nftnl_obj *obj, uint16_t attr)
+uint32_t nftnl_obj_get_u32(const struct nftnl_obj *obj, uint16_t attr)
{
const void *ret = nftnl_obj_get(obj, attr);
return ret == NULL ? 0 : *((uint32_t *)ret);
}
EXPORT_SYMBOL(nftnl_obj_get_u64);
-uint64_t nftnl_obj_get_u64(struct nftnl_obj *obj, uint16_t attr)
+uint64_t nftnl_obj_get_u64(const struct nftnl_obj *obj, uint16_t attr)
{
const void *ret = nftnl_obj_get(obj, attr);
return ret == NULL ? 0 : *((uint64_t *)ret);
}
EXPORT_SYMBOL(nftnl_obj_get_str);
-const char *nftnl_obj_get_str(struct nftnl_obj *obj, uint16_t attr)
+const char *nftnl_obj_get_str(const struct nftnl_obj *obj, uint16_t attr)
{
return nftnl_obj_get(obj, attr);
}
@@ -235,6 +278,8 @@ void nftnl_obj_nlmsg_build_payload(struct nlmsghdr *nlh,
mnl_attr_put_u32(nlh, NFTA_OBJ_TYPE, htonl(obj->ops->type));
if (obj->flags & (1 << NFTNL_OBJ_HANDLE))
mnl_attr_put_u64(nlh, NFTA_OBJ_HANDLE, htobe64(obj->handle));
+ if (obj->flags & (1 << NFTNL_OBJ_USERDATA))
+ mnl_attr_put(nlh, NFTA_OBJ_USERDATA, obj->user.len, obj->user.data);
if (obj->ops) {
struct nlattr *nest = mnl_attr_nest_start(nlh, NFTA_OBJ_DATA);
@@ -269,6 +314,10 @@ static int nftnl_obj_parse_attr_cb(const struct nlattr *attr, void *data)
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
+ case NFTA_OBJ_USERDATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+ abi_breakage();
+ break;
}
tb[type] = attr;
@@ -315,6 +364,11 @@ int nftnl_obj_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_obj *obj)
obj->handle = be64toh(mnl_attr_get_u64(tb[NFTA_OBJ_HANDLE]));
obj->flags |= (1 << NFTNL_OBJ_HANDLE);
}
+ if (tb[NFTA_OBJ_USERDATA]) {
+ nftnl_obj_set_data(obj, NFTNL_OBJ_USERDATA,
+ mnl_attr_get_payload(tb[NFTA_OBJ_USERDATA]),
+ mnl_attr_get_payload_len(tb[NFTA_OBJ_USERDATA]));
+ }
obj->family = nfg->nfgen_family;
obj->flags |= (1 << NFTNL_OBJ_FAMILY);
@@ -358,46 +412,38 @@ int nftnl_obj_parse_file(struct nftnl_obj *obj, enum nftnl_parse_type type,
return nftnl_obj_do_parse(obj, type, fp, err, NFTNL_PARSE_FILE);
}
-static int nftnl_obj_snprintf_dflt(char *buf, size_t size,
+static int nftnl_obj_snprintf_dflt(char *buf, size_t remain,
const struct nftnl_obj *obj,
uint32_t type, uint32_t flags)
{
const char *name = obj->ops ? obj->ops->name : "(unknown)";
- int ret, remain = size, offset = 0;
+ int ret, offset = 0;
- ret = snprintf(buf, size, "table %s name %s use %u [ %s ",
+ ret = snprintf(buf, remain, "table %s name %s use %u [ %s ",
obj->table, obj->name, obj->use, name);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (obj->ops) {
- ret = obj->ops->snprintf(buf + offset, offset, type, flags,
- obj);
+ ret = obj->ops->output(buf + offset, remain, flags, obj);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- ret = snprintf(buf + offset, offset, "]");
+ ret = snprintf(buf + offset, remain, "]");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
-static int nftnl_obj_cmd_snprintf(char *buf, size_t size,
+static int nftnl_obj_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_obj *obj, 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_obj_snprintf_dflt(buf + offset, remain, obj, type,
- flags);
- break;
- case NFTNL_OUTPUT_JSON:
- case NFTNL_OUTPUT_XML:
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ ret = nftnl_obj_snprintf_dflt(buf + offset, remain, obj, type, flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/rule.c b/src/rule.c
index 8d7e068..a52012b 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -330,6 +330,12 @@ void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr)
list_add_tail(&expr->head, &r->expr_list);
}
+EXPORT_SYMBOL(nftnl_rule_del_expr);
+void nftnl_rule_del_expr(struct nftnl_expr *expr)
+{
+ list_del(&expr->head);
+}
+
static int nftnl_rule_parse_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
@@ -539,50 +545,59 @@ int nftnl_rule_parse_file(struct nftnl_rule *r, enum nftnl_parse_type type,
return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE);
}
-static int nftnl_rule_snprintf_default(char *buf, size_t size,
+static int nftnl_rule_snprintf_default(char *buf, size_t remain,
const struct nftnl_rule *r,
uint32_t type, uint32_t flags)
{
struct nftnl_expr *expr;
- int ret, remain = size, offset = 0, i;
+ int ret, offset = 0, i;
+ const char *sep = "";
if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
- ret = snprintf(buf + offset, remain, "%s ",
+ ret = snprintf(buf + offset, remain, "%s%s", sep,
nftnl_family2str(r->family));
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_TABLE)) {
- ret = snprintf(buf + offset, remain, "%s ",
+ ret = snprintf(buf + offset, remain, "%s%s", sep,
r->table);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
- ret = snprintf(buf + offset, remain, "%s ",
+ ret = snprintf(buf + offset, remain, "%s%s", sep,
r->chain);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
- ret = snprintf(buf + offset, remain, "%llu ",
- (unsigned long long)r->handle);
+ ret = snprintf(buf + offset, remain, "%s%" PRIu64, sep,
+ r->handle);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_POSITION)) {
- ret = snprintf(buf + offset, remain, "%llu ",
- (unsigned long long)r->position);
+ ret = snprintf(buf + offset, remain, "%s%" PRIu64, sep,
+ r->position);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_ID)) {
- ret = snprintf(buf + offset, remain, "%u ", r->id);
+ ret = snprintf(buf + offset, remain, "%s%u", sep, r->id);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
if (r->flags & (1 << NFTNL_RULE_POSITION_ID)) {
- ret = snprintf(buf + offset, remain, "%u ", r->position_id);
+ ret = snprintf(buf + offset, remain, "%s%u", sep,
+ r->position_id);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = " ";
}
ret = snprintf(buf + offset, remain, "\n");
@@ -607,12 +622,13 @@ static int nftnl_rule_snprintf_default(char *buf, size_t size,
for (i = 0; i < r->user.len; i++) {
char *c = r->user.data;
- ret = snprintf(buf + offset, remain, "%c",
- isalnum(c[i]) ? c[i] : 0);
+ ret = snprintf(buf + offset, remain,
+ isprint(c[i]) ? "%c" : "\\x%02hhx",
+ c[i]);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- ret = snprintf(buf + offset, remain, " }\n");
+ ret = snprintf(buf + offset, remain, " }");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
@@ -620,27 +636,21 @@ static int nftnl_rule_snprintf_default(char *buf, size_t size,
return offset;
}
-static int nftnl_rule_cmd_snprintf(char *buf, size_t size,
+static int nftnl_rule_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_rule *r, uint32_t cmd,
uint32_t type, uint32_t flags)
{
- int ret, remain = size, offset = 0;
uint32_t inner_flags = flags;
+ int ret, offset = 0;
inner_flags &= ~NFTNL_OF_EVENT_ANY;
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type,
- inner_flags);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- case NFTNL_OUTPUT_JSON:
- case NFTNL_OUTPUT_XML:
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
+ ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type,
+ inner_flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/ruleset.c b/src/ruleset.c
index 2468bd4..185aa48 100644
--- a/src/ruleset.c
+++ b/src/ruleset.c
@@ -305,51 +305,15 @@ int nftnl_ruleset_parse_file(struct nftnl_ruleset *rs, enum nftnl_parse_type typ
return nftnl_ruleset_parse_file_cb(type, fp, err, rs, nftnl_ruleset_cb);
}
-static const char *nftnl_ruleset_o_opentag(uint32_t type)
-{
- switch (type) {
- case NFTNL_OUTPUT_JSON:
- return "{\"nftables\":[";
- case NFTNL_OUTPUT_XML:
- default:
- return "";
- }
-}
-
-static const char *nftnl_ruleset_o_separator(void *obj, uint32_t type)
-{
- if (obj == NULL)
- return "";
-
- switch (type) {
- case NFTNL_OUTPUT_JSON:
- return ",";
- case NFTNL_OUTPUT_DEFAULT:
- return "\n";
- default:
- return "";
- }
-}
-
-static const char *nftnl_ruleset_o_closetag(uint32_t type)
-{
- switch (type) {
- case NFTNL_OUTPUT_JSON:
- return "]}";
- case NFTNL_OUTPUT_XML:
- default:
- return "";
- }
-}
-
static int
-nftnl_ruleset_snprintf_table(char *buf, size_t size,
+nftnl_ruleset_snprintf_table(char *buf, size_t remain,
const struct nftnl_ruleset *rs, uint32_t type,
uint32_t flags)
{
struct nftnl_table *t;
struct nftnl_table_list_iter *ti;
- int ret, remain = size, offset = 0;
+ const char *sep = "";
+ int ret, offset = 0;
ti = nftnl_table_list_iter_create(rs->table_list);
if (ti == NULL)
@@ -357,14 +321,14 @@ nftnl_ruleset_snprintf_table(char *buf, size_t size,
t = nftnl_table_list_iter_next(ti);
while (t != NULL) {
+ ret = snprintf(buf + offset, remain, "%s", sep);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
ret = nftnl_table_snprintf(buf + offset, remain, t, type, flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
t = nftnl_table_list_iter_next(ti);
-
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(t, type));
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = "\n";
}
nftnl_table_list_iter_destroy(ti);
@@ -372,13 +336,14 @@ nftnl_ruleset_snprintf_table(char *buf, size_t size,
}
static int
-nftnl_ruleset_snprintf_chain(char *buf, size_t size,
+nftnl_ruleset_snprintf_chain(char *buf, size_t remain,
const struct nftnl_ruleset *rs, uint32_t type,
uint32_t flags)
{
struct nftnl_chain *c;
struct nftnl_chain_list_iter *ci;
- int ret, remain = size, offset = 0;
+ const char *sep = "";
+ int ret, offset = 0;
ci = nftnl_chain_list_iter_create(rs->chain_list);
if (ci == NULL)
@@ -386,14 +351,14 @@ nftnl_ruleset_snprintf_chain(char *buf, size_t size,
c = nftnl_chain_list_iter_next(ci);
while (c != NULL) {
+ ret = snprintf(buf + offset, remain, "%s", sep);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
ret = nftnl_chain_snprintf(buf + offset, remain, c, type, flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
c = nftnl_chain_list_iter_next(ci);
-
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(c, type));
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = "\n";
}
nftnl_chain_list_iter_destroy(ci);
@@ -401,13 +366,14 @@ nftnl_ruleset_snprintf_chain(char *buf, size_t size,
}
static int
-nftnl_ruleset_snprintf_set(char *buf, size_t size,
+nftnl_ruleset_snprintf_set(char *buf, size_t remain,
const struct nftnl_ruleset *rs, uint32_t type,
uint32_t flags)
{
struct nftnl_set *s;
struct nftnl_set_list_iter *si;
- int ret, remain = size, offset = 0;
+ const char *sep = "";
+ int ret, offset = 0;
si = nftnl_set_list_iter_create(rs->set_list);
if (si == NULL)
@@ -415,14 +381,14 @@ nftnl_ruleset_snprintf_set(char *buf, size_t size,
s = nftnl_set_list_iter_next(si);
while (s != NULL) {
+ ret = snprintf(buf + offset, remain, "%s", sep);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
ret = nftnl_set_snprintf(buf + offset, remain, s, type, flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
s = nftnl_set_list_iter_next(si);
-
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(s, type));
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = "\n";
}
nftnl_set_list_iter_destroy(si);
@@ -430,13 +396,14 @@ nftnl_ruleset_snprintf_set(char *buf, size_t size,
}
static int
-nftnl_ruleset_snprintf_rule(char *buf, size_t size,
+nftnl_ruleset_snprintf_rule(char *buf, size_t remain,
const struct nftnl_ruleset *rs, uint32_t type,
uint32_t flags)
{
struct nftnl_rule *r;
struct nftnl_rule_list_iter *ri;
- int ret, remain = size, offset = 0;
+ const char *sep = "";
+ int ret, offset = 0;
ri = nftnl_rule_list_iter_create(rs->rule_list);
if (ri == NULL)
@@ -444,14 +411,14 @@ nftnl_ruleset_snprintf_rule(char *buf, size_t size,
r = nftnl_rule_list_iter_next(ri);
while (r != NULL) {
+ ret = snprintf(buf + offset, remain, "%s", sep);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
ret = nftnl_rule_snprintf(buf + offset, remain, r, type, flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
r = nftnl_rule_list_iter_next(ri);
-
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(r, type));
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+ sep = "\n";
}
nftnl_rule_list_iter_destroy(ri);
@@ -459,12 +426,13 @@ nftnl_ruleset_snprintf_rule(char *buf, size_t size,
}
static int
-nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs,
- uint32_t cmd, uint32_t type, uint32_t flags)
+nftnl_ruleset_do_snprintf(char *buf, size_t remain,
+ const struct nftnl_ruleset *rs,
+ uint32_t cmd, uint32_t type, uint32_t flags)
{
- int ret, remain = size, offset = 0;
- void *prev = NULL;
uint32_t inner_flags = flags;
+ const char *sep = "";
+ int ret, offset = 0;
/* dont pass events flags to child calls of _snprintf() */
inner_flags &= ~NFTNL_OF_EVENT_ANY;
@@ -476,13 +444,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (ret > 0)
- prev = rs->table_list;
+ sep = "\n";
}
if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST) &&
(!nftnl_chain_list_is_empty(rs->chain_list))) {
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(prev, type));
+ ret = snprintf(buf + offset, remain, "%s", sep);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_ruleset_snprintf_chain(buf + offset, remain, rs,
@@ -490,13 +457,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (ret > 0)
- prev = rs->chain_list;
+ sep = "\n";
}
if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST) &&
(!nftnl_set_list_is_empty(rs->set_list))) {
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(prev, type));
+ ret = snprintf(buf + offset, remain, "%s", sep);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_ruleset_snprintf_set(buf + offset, remain, rs,
@@ -504,13 +470,12 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (ret > 0)
- prev = rs->set_list;
+ sep = "\n";
}
if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST) &&
(!nftnl_rule_list_is_empty(rs->rule_list))) {
- ret = snprintf(buf + offset, remain, "%s",
- nftnl_ruleset_o_separator(prev, type));
+ ret = snprintf(buf + offset, remain, "%s", sep);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = nftnl_ruleset_snprintf_rule(buf + offset, remain, rs,
@@ -521,21 +486,6 @@ nftnl_ruleset_do_snprintf(char *buf, size_t size, const struct nftnl_ruleset *rs
return offset;
}
-static int nftnl_ruleset_cmd_snprintf(char *buf, size_t size,
- const struct nftnl_ruleset *r, uint32_t cmd,
- uint32_t type, uint32_t flags)
-{
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- case NFTNL_OUTPUT_JSON:
- return nftnl_ruleset_do_snprintf(buf, size, r, cmd, type, flags);
- case NFTNL_OUTPUT_XML:
- default:
- errno = EOPNOTSUPP;
- return -1;
- }
-}
-
EXPORT_SYMBOL(nftnl_ruleset_snprintf);
int nftnl_ruleset_snprintf(char *buf, size_t size, const struct nftnl_ruleset *r,
uint32_t type, uint32_t flags)
@@ -543,17 +493,12 @@ int nftnl_ruleset_snprintf(char *buf, size_t size, const struct nftnl_ruleset *r
if (size)
buf[0] = '\0';
- switch (type) {
- case NFTNL_OUTPUT_DEFAULT:
- case NFTNL_OUTPUT_JSON:
- return nftnl_ruleset_cmd_snprintf(buf, size, r,
- nftnl_flag2cmd(flags), type,
- flags);
- case NFTNL_OUTPUT_XML:
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT) {
errno = EOPNOTSUPP;
return -1;
}
+ return nftnl_ruleset_do_snprintf(buf, size, r, nftnl_flag2cmd(flags),
+ type, flags);
}
static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs,
@@ -562,6 +507,7 @@ static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs
int len = 0, ret = 0;
struct nftnl_table *t;
struct nftnl_table_list_iter *ti;
+ const char *sep = "";
ti = nftnl_table_list_iter_create(rs->table_list);
if (ti == NULL)
@@ -569,19 +515,21 @@ static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs
t = nftnl_table_list_iter_next(ti);
while (t != NULL) {
- ret = nftnl_table_fprintf(fp, t, type, flags);
+ ret = fprintf(fp, "%s", sep);
if (ret < 0)
goto err;
len += ret;
- t = nftnl_table_list_iter_next(ti);
-
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(t, type));
+ ret = nftnl_table_fprintf(fp, t, type, flags);
if (ret < 0)
goto err;
len += ret;
+
+ t = nftnl_table_list_iter_next(ti);
+ sep = "\n";
+
}
nftnl_table_list_iter_destroy(ti);
@@ -597,6 +545,7 @@ static int nftnl_ruleset_fprintf_chains(FILE *fp, const struct nftnl_ruleset *rs
int len = 0, ret = 0;
struct nftnl_chain *o;
struct nftnl_chain_list_iter *i;
+ const char *sep = "";
i = nftnl_chain_list_iter_create(rs->chain_list);
if (i == NULL)
@@ -604,19 +553,20 @@ static int nftnl_ruleset_fprintf_chains(FILE *fp, const struct nftnl_ruleset *rs
o = nftnl_chain_list_iter_next(i);
while (o != NULL) {
- ret = nftnl_chain_fprintf(fp, o, type, flags);
+ ret = fprintf(fp, "%s", sep);
if (ret < 0)
goto err;
len += ret;
- o = nftnl_chain_list_iter_next(i);
-
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type));
+ ret = nftnl_chain_fprintf(fp, o, type, flags);
if (ret < 0)
goto err;
len += ret;
+
+ o = nftnl_chain_list_iter_next(i);
+ sep = "\n";
}
nftnl_chain_list_iter_destroy(i);
@@ -632,6 +582,7 @@ static int nftnl_ruleset_fprintf_sets(FILE *fp, const struct nftnl_ruleset *rs,
int len = 0, ret = 0;
struct nftnl_set *o;
struct nftnl_set_list_iter *i;
+ const char *sep = "";
i = nftnl_set_list_iter_create(rs->set_list);
if (i == NULL)
@@ -639,19 +590,20 @@ static int nftnl_ruleset_fprintf_sets(FILE *fp, const struct nftnl_ruleset *rs,
o = nftnl_set_list_iter_next(i);
while (o != NULL) {
- ret = nftnl_set_fprintf(fp, o, type, flags);
+ ret = fprintf(fp, "%s", sep);
if (ret < 0)
goto err;
len += ret;
- o = nftnl_set_list_iter_next(i);
-
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type));
+ ret = nftnl_set_fprintf(fp, o, type, flags);
if (ret < 0)
goto err;
len += ret;
+
+ o = nftnl_set_list_iter_next(i);
+ sep = "\n";
}
nftnl_set_list_iter_destroy(i);
@@ -667,6 +619,7 @@ static int nftnl_ruleset_fprintf_rules(FILE *fp, const struct nftnl_ruleset *rs,
int len = 0, ret = 0;
struct nftnl_rule *o;
struct nftnl_rule_list_iter *i;
+ const char *sep = "";
i = nftnl_rule_list_iter_create(rs->rule_list);
if (i == NULL)
@@ -674,19 +627,20 @@ static int nftnl_ruleset_fprintf_rules(FILE *fp, const struct nftnl_ruleset *rs,
o = nftnl_rule_list_iter_next(i);
while (o != NULL) {
- ret = nftnl_rule_fprintf(fp, o, type, flags);
+ ret = fprintf(fp, "%s", sep);
if (ret < 0)
goto err;
len += ret;
- o = nftnl_rule_list_iter_next(i);
-
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(o, type));
+ ret = nftnl_rule_fprintf(fp, o, type, flags);
if (ret < 0)
goto err;
len += ret;
+
+ o = nftnl_rule_list_iter_next(i);
+ sep = "\n";
}
nftnl_rule_list_iter_destroy(i);
@@ -705,60 +659,54 @@ static int nftnl_ruleset_cmd_fprintf(FILE *fp, const struct nftnl_ruleset *rs,
uint32_t cmd, uint32_t type, uint32_t flags)
{
int len = 0, ret = 0;
- void *prev = NULL;
uint32_t inner_flags = flags;
+ const char *sep = "";
/* dont pass events flags to child calls of _snprintf() */
inner_flags &= ~NFTNL_OF_EVENT_ANY;
- ret = fprintf(fp, "%s", nftnl_ruleset_o_opentag(type));
- NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
-
if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_TABLELIST)) &&
(!nftnl_table_list_is_empty(rs->table_list))) {
ret = nftnl_ruleset_fprintf_tables(fp, rs, type, inner_flags);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
if (ret > 0)
- prev = rs->table_list;
+ sep = "\n";
}
if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST)) &&
(!nftnl_chain_list_is_empty(rs->chain_list))) {
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type));
+ ret = fprintf(fp, "%s", sep);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
ret = nftnl_ruleset_fprintf_chains(fp, rs, type, inner_flags);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
if (ret > 0)
- prev = rs->chain_list;
+ sep = "\n";
}
if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST)) &&
(!nftnl_set_list_is_empty(rs->set_list))) {
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type));
+ ret = fprintf(fp, "%s", sep);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
ret = nftnl_ruleset_fprintf_sets(fp, rs, type, inner_flags);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
if (ret > 0)
- prev = rs->set_list;
+ sep = "\n";
}
if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST)) &&
(!nftnl_rule_list_is_empty(rs->rule_list))) {
- ret = fprintf(fp, "%s", nftnl_ruleset_o_separator(prev, type));
+ ret = fprintf(fp, "%s", sep);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
ret = nftnl_ruleset_fprintf_rules(fp, rs, type, inner_flags);
NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
}
- ret = fprintf(fp, "%s", nftnl_ruleset_o_closetag(type));
- NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
-
return len;
}
diff --git a/src/set.c b/src/set.c
index 651dcfa..b51ff9e 100644
--- a/src/set.c
+++ b/src/set.c
@@ -37,6 +37,7 @@ struct nftnl_set *nftnl_set_alloc(void)
return NULL;
INIT_LIST_HEAD(&s->element_list);
+ INIT_LIST_HEAD(&s->expr_list);
return s;
}
@@ -44,6 +45,7 @@ EXPORT_SYMBOL(nftnl_set_free);
void nftnl_set_free(const struct nftnl_set *s)
{
struct nftnl_set_elem *elem, *tmp;
+ struct nftnl_expr *expr, *next;
if (s->flags & (1 << NFTNL_SET_TABLE))
xfree(s->table);
@@ -52,6 +54,11 @@ void nftnl_set_free(const struct nftnl_set *s)
if (s->flags & (1 << NFTNL_SET_USERDATA))
xfree(s->user.data);
+ list_for_each_entry_safe(expr, next, &s->expr_list, head) {
+ list_del(&expr->head);
+ nftnl_expr_free(expr);
+ }
+
list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
list_del(&elem->head);
nftnl_set_elem_free(elem);
@@ -68,6 +75,8 @@ bool nftnl_set_is_set(const struct nftnl_set *s, uint16_t attr)
EXPORT_SYMBOL(nftnl_set_unset);
void nftnl_set_unset(struct nftnl_set *s, uint16_t attr)
{
+ struct nftnl_expr *expr, *tmp;
+
if (!(s->flags & (1 << attr)))
return;
@@ -96,6 +105,13 @@ void nftnl_set_unset(struct nftnl_set *s, uint16_t attr)
case NFTNL_SET_USERDATA:
xfree(s->user.data);
break;
+ case NFTNL_SET_EXPR:
+ case NFTNL_SET_EXPRESSIONS:
+ list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
+ list_del(&expr->head);
+ nftnl_expr_free(expr);
+ }
+ break;
default:
return;
}
@@ -122,6 +138,8 @@ EXPORT_SYMBOL(nftnl_set_set_data);
int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
uint32_t data_len)
{
+ struct nftnl_expr *expr, *tmp;
+
nftnl_assert_attr_exists(attr, NFTNL_SET_MAX);
nftnl_assert_validate(data, nftnl_set_validate, attr, data_len);
@@ -176,8 +194,14 @@ int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
memcpy(&s->desc.size, data, sizeof(s->desc.size));
break;
case NFTNL_SET_DESC_CONCAT:
+ if (data_len > sizeof(s->desc.field_len))
+ return -1;
+
memcpy(&s->desc.field_len, data, data_len);
- while (s->desc.field_len[++s->desc.field_count]);
+ while (s->desc.field_len[++s->desc.field_count]) {
+ if (s->desc.field_count >= NFT_REG32_COUNT)
+ break;
+ }
break;
case NFTNL_SET_TIMEOUT:
memcpy(&s->timeout, data, sizeof(s->timeout));
@@ -195,6 +219,15 @@ int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
memcpy(s->user.data, data, data_len);
s->user.len = data_len;
break;
+ case NFTNL_SET_EXPR:
+ list_for_each_entry_safe(expr, tmp, &s->expr_list, head) {
+ list_del(&expr->head);
+ nftnl_expr_free(expr);
+ }
+
+ expr = (void *)data;
+ list_add(&expr->head, &s->expr_list);
+ break;
}
s->flags |= (1 << attr);
return 0;
@@ -228,6 +261,8 @@ EXPORT_SYMBOL(nftnl_set_get_data);
const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr,
uint32_t *data_len)
{
+ struct nftnl_expr *expr;
+
if (!(s->flags & (1 << attr)))
return NULL;
@@ -283,6 +318,10 @@ const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr,
case NFTNL_SET_USERDATA:
*data_len = s->user.len;
return s->user.data;
+ case NFTNL_SET_EXPR:
+ list_for_each_entry(expr, &s->expr_list, head)
+ break;
+ return expr;
}
return NULL;
}
@@ -401,6 +440,8 @@ nftnl_set_nlmsg_build_desc_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
{
+ int num_exprs = 0;
+
if (s->flags & (1 << NFTNL_SET_TABLE))
mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
if (s->flags & (1 << NFTNL_SET_NAME))
@@ -432,8 +473,55 @@ void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
if (s->flags & (1 << NFTNL_SET_USERDATA))
mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
+ if (!list_empty(&s->expr_list)) {
+ struct nftnl_expr *expr;
+
+ list_for_each_entry(expr, &s->expr_list, head)
+ num_exprs++;
+
+ if (num_exprs == 1) {
+ struct nlattr *nest1;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
+ list_for_each_entry(expr, &s->expr_list, head)
+ nftnl_expr_build_payload(nlh, expr);
+
+ mnl_attr_nest_end(nlh, nest1);
+ } else if (num_exprs > 1) {
+ struct nlattr *nest1, *nest2;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPRESSIONS);
+ list_for_each_entry(expr, &s->expr_list, head) {
+ nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
+ nftnl_expr_build_payload(nlh, expr);
+ mnl_attr_nest_end(nlh, nest2);
+ }
+ mnl_attr_nest_end(nlh, nest1);
+ }
+ }
+}
+
+EXPORT_SYMBOL(nftnl_set_add_expr);
+void nftnl_set_add_expr(struct nftnl_set *s, struct nftnl_expr *expr)
+{
+ list_add_tail(&expr->head, &s->expr_list);
}
+EXPORT_SYMBOL(nftnl_set_expr_foreach);
+int nftnl_set_expr_foreach(const struct nftnl_set *s,
+ int (*cb)(struct nftnl_expr *e, void *data),
+ void *data)
+{
+ struct nftnl_expr *cur, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(cur, tmp, &s->expr_list, head) {
+ ret = cb(cur, data);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data)
{
@@ -473,6 +561,8 @@ static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data)
abi_breakage();
break;
case NFTA_SET_DESC:
+ case NFTA_SET_EXPR:
+ case NFTA_SET_EXPRESSIONS:
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
abi_breakage();
break;
@@ -558,6 +648,7 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
{
struct nlattr *tb[NFTA_SET_MAX+1] = {};
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
+ struct nftnl_expr *expr, *next;
int ret;
if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
@@ -635,11 +726,40 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
if (ret < 0)
return ret;
}
+ if (tb[NFTA_SET_EXPR]) {
+ expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
+ if (!expr)
+ goto out_set_expr;
+
+ list_add(&expr->head, &s->expr_list);
+ s->flags |= (1 << NFTNL_SET_EXPR);
+ } else if (tb[NFTA_SET_EXPRESSIONS]) {
+ struct nlattr *attr;
+
+ mnl_attr_for_each_nested(attr, tb[NFTA_SET_EXPRESSIONS]) {
+ if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
+ goto out_set_expr;
+
+ expr = nftnl_expr_parse(attr);
+ if (expr == NULL)
+ goto out_set_expr;
+
+ list_add_tail(&expr->head, &s->expr_list);
+ }
+ s->flags |= (1 << NFTNL_SET_EXPRESSIONS);
+ }
s->family = nfg->nfgen_family;
s->flags |= (1 << NFTNL_SET_FAMILY);
return 0;
+out_set_expr:
+ list_for_each_entry_safe(expr, next, &s->expr_list, head) {
+ list_del(&expr->head);
+ nftnl_expr_free(expr);
+ }
+
+ return -1;
}
static int nftnl_set_do_parse(struct nftnl_set *s, enum nftnl_parse_type type,
@@ -678,13 +798,12 @@ int nftnl_set_parse_file(struct nftnl_set *s, enum nftnl_parse_type type,
return nftnl_set_do_parse(s, type, fp, err, NFTNL_PARSE_FILE);
}
-static int nftnl_set_snprintf_default(char *buf, size_t size,
+static int nftnl_set_snprintf_default(char *buf, size_t remain,
const struct nftnl_set *s,
uint32_t type, uint32_t flags)
{
- int ret;
- int remain = size, offset = 0;
struct nftnl_set_elem *elem;
+ int ret, offset = 0;
ret = snprintf(buf, remain, "%s %s %x",
s->name, s->table, s->set_flags);
@@ -723,37 +842,30 @@ static int nftnl_set_snprintf_default(char *buf, size_t size,
ret = snprintf(buf + offset, remain, "\t");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- ret = nftnl_set_elem_snprintf(buf + offset, remain, elem, type,
- flags);
+ ret = nftnl_set_elem_snprintf_default(buf + offset, remain,
+ elem);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
return offset;
}
-static int nftnl_set_cmd_snprintf(char *buf, size_t size,
+static int nftnl_set_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_set *s, uint32_t cmd,
uint32_t type, uint32_t flags)
{
- int ret, remain = size, offset = 0;
uint32_t inner_flags = flags;
+ int ret, offset = 0;
- if (type == NFTNL_OUTPUT_XML)
- return 0;
+ if (type != NFTNL_OUTPUT_DEFAULT)
+ return -1;
/* prevent set_elems to print as events */
inner_flags &= ~NFTNL_OF_EVENT_ANY;
- switch(type) {
- case NFTNL_OUTPUT_DEFAULT:
- ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
- inner_flags);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- default:
- return -1;
- }
-
+ ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
+ inner_flags);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/set_elem.c b/src/set_elem.c
index d3ce807..9207a0d 100644
--- a/src/set_elem.c
+++ b/src/set_elem.c
@@ -36,17 +36,21 @@ struct nftnl_set_elem *nftnl_set_elem_alloc(void)
if (s == NULL)
return NULL;
+ INIT_LIST_HEAD(&s->expr_list);
+
return s;
}
EXPORT_SYMBOL(nftnl_set_elem_free);
void nftnl_set_elem_free(struct nftnl_set_elem *s)
{
+ struct nftnl_expr *e, *tmp;
+
if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN))
xfree(s->data.chain);
- if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
- nftnl_expr_free(s->expr);
+ list_for_each_entry_safe(e, tmp, &s->expr_list, head)
+ nftnl_expr_free(e);
if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
xfree(s->user.data);
@@ -66,6 +70,8 @@ bool nftnl_set_elem_is_set(const struct nftnl_set_elem *s, uint16_t attr)
EXPORT_SYMBOL(nftnl_set_elem_unset);
void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr)
{
+ struct nftnl_expr *expr, *tmp;
+
if (!(s->flags & (1 << attr)))
return;
@@ -75,6 +81,7 @@ void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr)
break;
case NFTNL_SET_ELEM_FLAGS:
case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
+ case NFTNL_SET_ELEM_KEY_END: /* NFTA_SET_ELEM_KEY_END */
case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */
case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */
@@ -84,7 +91,9 @@ void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr)
xfree(s->user.data);
break;
case NFTNL_SET_ELEM_EXPR:
- nftnl_expr_free(s->expr);
+ case NFTNL_SET_ELEM_EXPRESSIONS:
+ list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
+ nftnl_expr_free(expr);
break;
case NFTNL_SET_ELEM_OBJREF:
xfree(s->objref);
@@ -107,6 +116,8 @@ EXPORT_SYMBOL(nftnl_set_elem_set);
int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr,
const void *data, uint32_t data_len)
{
+ struct nftnl_expr *expr, *tmp;
+
nftnl_assert_attr_exists(attr, NFTNL_SET_ELEM_MAX);
nftnl_assert_validate(data, nftnl_set_elem_validate, attr, data_len);
@@ -115,8 +126,12 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr,
memcpy(&s->set_elem_flags, data, sizeof(s->set_elem_flags));
break;
case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
- memcpy(&s->key.val, data, data_len);
- s->key.len = data_len;
+ if (nftnl_data_cpy(&s->key, data, data_len) < 0)
+ return -1;
+ break;
+ case NFTNL_SET_ELEM_KEY_END: /* NFTA_SET_ELEM_KEY_END */
+ if (nftnl_data_cpy(&s->key_end, data, data_len) < 0)
+ return -1;
break;
case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
memcpy(&s->data.verdict, data, sizeof(s->data.verdict));
@@ -130,8 +145,8 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr,
return -1;
break;
case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */
- memcpy(s->data.val, data, data_len);
- s->data.len = data_len;
+ if (nftnl_data_cpy(&s->data, data, data_len) < 0)
+ return -1;
break;
case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */
memcpy(&s->timeout, data, sizeof(s->timeout));
@@ -157,6 +172,13 @@ int nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr,
if (!s->objref)
return -1;
break;
+ case NFTNL_SET_ELEM_EXPR:
+ list_for_each_entry_safe(expr, tmp, &s->expr_list, head)
+ nftnl_expr_free(expr);
+
+ expr = (void *)data;
+ list_add(&expr->head, &s->expr_list);
+ break;
}
s->flags |= (1 << attr);
return 0;
@@ -183,6 +205,8 @@ int nftnl_set_elem_set_str(struct nftnl_set_elem *s, uint16_t attr, const char *
EXPORT_SYMBOL(nftnl_set_elem_get);
const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
{
+ struct nftnl_expr *expr;
+
if (!(s->flags & (1 << attr)))
return NULL;
@@ -193,6 +217,9 @@ const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t
case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
*data_len = s->key.len;
return &s->key.val;
+ case NFTNL_SET_ELEM_KEY_END: /* NFTA_SET_ELEM_KEY_END */
+ *data_len = s->key_end.len;
+ return &s->key_end.val;
case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
*data_len = sizeof(s->data.verdict);
return &s->data.verdict;
@@ -212,7 +239,9 @@ const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t
*data_len = s->user.len;
return s->user.data;
case NFTNL_SET_ELEM_EXPR:
- return s->expr;
+ list_for_each_entry(expr, &s->expr_list, head)
+ break;
+ return expr;
case NFTNL_SET_ELEM_OBJREF:
*data_len = strlen(s->objref) + 1;
return s->objref;
@@ -271,9 +300,13 @@ err:
return NULL;
}
+EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build_payload);
void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh,
struct nftnl_set_elem *e)
{
+ struct nftnl_expr *expr;
+ int num_exprs = 0;
+
if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
@@ -287,6 +320,14 @@ void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh,
mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
mnl_attr_nest_end(nlh, nest1);
}
+ if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
+ struct nlattr *nest1;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY_END);
+ mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key_end.len,
+ e->key_end.val);
+ mnl_attr_nest_end(nlh, nest1);
+ }
if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
struct nlattr *nest1, *nest2;
@@ -310,6 +351,31 @@ void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh,
mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
if (e->flags & (1 << NFTNL_SET_ELEM_OBJREF))
mnl_attr_put_strz(nlh, NFTA_SET_ELEM_OBJREF, e->objref);
+
+ if (!list_empty(&e->expr_list)) {
+ list_for_each_entry(expr, &e->expr_list, head)
+ num_exprs++;
+
+ if (num_exprs == 1) {
+ struct nlattr *nest1;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPR);
+ list_for_each_entry(expr, &e->expr_list, head)
+ nftnl_expr_build_payload(nlh, expr);
+
+ mnl_attr_nest_end(nlh, nest1);
+ } else if (num_exprs > 1) {
+ struct nlattr *nest1, *nest2;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_EXPRESSIONS);
+ list_for_each_entry(expr, &e->expr_list, head) {
+ nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
+ nftnl_expr_build_payload(nlh, expr);
+ mnl_attr_nest_end(nlh, nest2);
+ }
+ mnl_attr_nest_end(nlh, nest1);
+ }
+ }
}
static void nftnl_set_elem_nlmsg_build_def(struct nlmsghdr *nlh,
@@ -323,8 +389,9 @@ static void nftnl_set_elem_nlmsg_build_def(struct nlmsghdr *nlh,
mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
}
-static struct nlattr *nftnl_set_elem_build(struct nlmsghdr *nlh,
- struct nftnl_set_elem *elem, int i)
+EXPORT_SYMBOL(nftnl_set_elem_nlmsg_build);
+struct nlattr *nftnl_set_elem_nlmsg_build(struct nlmsghdr *nlh,
+ struct nftnl_set_elem *elem, int i)
{
struct nlattr *nest2;
@@ -349,11 +416,33 @@ void nftnl_set_elems_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set
nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
list_for_each_entry(elem, &s->element_list, head)
- nftnl_set_elem_build(nlh, elem, ++i);
+ nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
mnl_attr_nest_end(nlh, nest1);
}
+EXPORT_SYMBOL(nftnl_set_elem_add_expr);
+void nftnl_set_elem_add_expr(struct nftnl_set_elem *e, struct nftnl_expr *expr)
+{
+ list_add_tail(&expr->head, &e->expr_list);
+}
+
+EXPORT_SYMBOL(nftnl_set_elem_expr_foreach);
+int nftnl_set_elem_expr_foreach(struct nftnl_set_elem *e,
+ int (*cb)(struct nftnl_expr *e, void *data),
+ void *data)
+{
+ struct nftnl_expr *cur, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(cur, tmp, &e->expr_list, head) {
+ ret = cb(cur, data);
+ if (ret < 0)
+ return ret;
+ }
+ return 0;
+}
+
static int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
@@ -373,8 +462,10 @@ static int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr, void *data)
abi_breakage();
break;
case NFTA_SET_ELEM_KEY:
+ case NFTA_SET_ELEM_KEY_END:
case NFTA_SET_ELEM_DATA:
case NFTA_SET_ELEM_EXPR:
+ case NFTA_SET_ELEM_EXPRESSIONS:
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
abi_breakage();
break;
@@ -421,6 +512,13 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest
goto out_set_elem;
e->flags |= (1 << NFTNL_SET_ELEM_KEY);
}
+ if (tb[NFTA_SET_ELEM_KEY_END]) {
+ ret = nftnl_parse_data(&e->key_end, tb[NFTA_SET_ELEM_KEY_END],
+ &type);
+ if (ret < 0)
+ goto out_set_elem;
+ e->flags |= (1 << NFTNL_SET_ELEM_KEY_END);
+ }
if (tb[NFTA_SET_ELEM_DATA]) {
ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
if (ret < 0)
@@ -439,12 +537,32 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest
}
}
if (tb[NFTA_SET_ELEM_EXPR]) {
- e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
- if (e->expr == NULL) {
+ struct nftnl_expr *expr;
+
+ expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
+ if (expr == NULL) {
ret = -1;
goto out_set_elem;
}
+ list_add_tail(&expr->head, &e->expr_list);
e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
+ } else if (tb[NFTA_SET_ELEM_EXPRESSIONS]) {
+ struct nftnl_expr *expr;
+ struct nlattr *attr;
+
+ mnl_attr_for_each_nested(attr, tb[NFTA_SET_ELEM_EXPRESSIONS]) {
+ if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM) {
+ ret = -1;
+ goto out_set_elem;
+ }
+ expr = nftnl_expr_parse(attr);
+ if (expr == NULL) {
+ ret = -1;
+ goto out_set_elem;
+ }
+ list_add_tail(&expr->head, &e->expr_list);
+ }
+ e->flags |= (1 << NFTNL_SET_ELEM_EXPRESSIONS);
}
if (tb[NFTA_SET_ELEM_USERDATA]) {
const void *udata =
@@ -457,7 +575,7 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest
e->user.data = malloc(e->user.len);
if (e->user.data == NULL) {
ret = -1;
- goto out_expr;
+ goto out_set_elem;
}
memcpy(e->user.data, udata, e->user.len);
e->flags |= (1 << NFTNL_RULE_USERDATA);
@@ -475,8 +593,6 @@ static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest
list_add_tail(&e->head, &s->element_list);
return 0;
-out_expr:
- nftnl_expr_free(e->expr);
out_set_elem:
nftnl_set_elem_free(e);
return ret;
@@ -584,67 +700,72 @@ int nftnl_set_elem_parse_file(struct nftnl_set_elem *e, enum nftnl_parse_type ty
return -1;
}
-static int nftnl_set_elem_snprintf_default(char *buf, size_t size,
- const struct nftnl_set_elem *e)
+int nftnl_set_elem_snprintf_default(char *buf, size_t remain,
+ const struct nftnl_set_elem *e)
{
- int ret, remain = size, offset = 0, i;
+ int ret, dregtype = DATA_VALUE, offset = 0, i;
ret = snprintf(buf, remain, "element ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- for (i = 0; i < div_round_up(e->key.len, sizeof(uint32_t)); i++) {
- ret = snprintf(buf + offset, remain, "%.8x ", e->key.val[i]);
+ ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key,
+ DATA_F_NOPFX, DATA_VALUE);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ if (e->flags & (1 << NFTNL_SET_ELEM_KEY_END)) {
+ ret = snprintf(buf + offset, remain, " - ");
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
+
+ ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->key_end,
+ DATA_F_NOPFX, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
ret = snprintf(buf + offset, remain, " : ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- for (i = 0; i < div_round_up(e->data.len, sizeof(uint32_t)); i++) {
- ret = snprintf(buf + offset, remain, "%.8x ", e->data.val[i]);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- }
+ if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
+ dregtype = DATA_VERDICT;
+
+ ret = nftnl_data_reg_snprintf(buf + offset, remain, &e->data,
+ DATA_F_NOPFX, dregtype);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
ret = snprintf(buf + offset, remain, "%u [end]", e->set_elem_flags);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
if (e->user.len) {
- ret = snprintf(buf + offset, remain, " userdata = {");
+ ret = snprintf(buf + offset, remain, " userdata = { ");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
for (i = 0; i < e->user.len; i++) {
char *c = e->user.data;
- ret = snprintf(buf + offset, remain, "%c",
- isalnum(c[i]) ? c[i] : 0);
+ ret = snprintf(buf + offset, remain,
+ isprint(c[i]) ? "%c" : "\\x%02hhx",
+ c[i]);
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
- ret = snprintf(buf + offset, remain, " }\n");
+ ret = snprintf(buf + offset, remain, " }");
SNPRINTF_BUFFER_SIZE(ret, remain, offset);
}
return offset;
}
-static int nftnl_set_elem_cmd_snprintf(char *buf, size_t size,
+static int nftnl_set_elem_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_set_elem *e,
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_set_elem_snprintf_default(buf + offset, remain, e);
- 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_set_elem_snprintf_default(buf + offset, remain, e);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
@@ -669,7 +790,7 @@ static int nftnl_set_elem_do_snprintf(char *buf, size_t size, const void *e,
}
EXPORT_SYMBOL(nftnl_set_elem_fprintf);
-int nftnl_set_elem_fprintf(FILE *fp, struct nftnl_set_elem *se, uint32_t type,
+int nftnl_set_elem_fprintf(FILE *fp, const struct nftnl_set_elem *se, uint32_t type,
uint32_t flags)
{
return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
@@ -781,7 +902,7 @@ int nftnl_set_elems_nlmsg_build_payload_iter(struct nlmsghdr *nlh,
nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
elem = nftnl_set_elems_iter_next(iter);
while (elem != NULL) {
- nest2 = nftnl_set_elem_build(nlh, elem, ++i);
+ nest2 = nftnl_set_elem_nlmsg_build(nlh, elem, ++i);
if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
/* Go back to previous not to miss this element */
iter->cur = list_entry(iter->cur->head.prev,
diff --git a/src/table.c b/src/table.c
index 94d522b..59e7053 100644
--- a/src/table.c
+++ b/src/table.c
@@ -34,6 +34,11 @@ struct nftnl_table {
uint64_t handle;
uint32_t use;
uint32_t flags;
+ uint32_t owner;
+ struct {
+ void *data;
+ uint32_t len;
+ } user;
};
EXPORT_SYMBOL(nftnl_table_alloc);
@@ -47,6 +52,8 @@ void nftnl_table_free(const struct nftnl_table *t)
{
if (t->flags & (1 << NFTNL_TABLE_NAME))
xfree(t->name);
+ if (t->flags & (1 << NFTNL_TABLE_USERDATA))
+ xfree(t->user.data);
xfree(t);
}
@@ -70,8 +77,8 @@ void nftnl_table_unset(struct nftnl_table *t, uint16_t attr)
case NFTNL_TABLE_FLAGS:
case NFTNL_TABLE_HANDLE:
case NFTNL_TABLE_FAMILY:
- break;
case NFTNL_TABLE_USE:
+ case NFTNL_TABLE_OWNER:
break;
}
t->flags &= ~(1 << attr);
@@ -111,6 +118,19 @@ int nftnl_table_set_data(struct nftnl_table *t, uint16_t attr,
case NFTNL_TABLE_USE:
memcpy(&t->use, data, sizeof(t->use));
break;
+ case NFTNL_TABLE_USERDATA:
+ if (t->flags & (1 << NFTNL_TABLE_USERDATA))
+ xfree(t->user.data);
+
+ t->user.data = malloc(data_len);
+ if (!t->user.data)
+ return -1;
+ memcpy(t->user.data, data, data_len);
+ t->user.len = data_len;
+ break;
+ case NFTNL_TABLE_OWNER:
+ memcpy(&t->owner, data, sizeof(t->owner));
+ break;
}
t->flags |= (1 << attr);
return 0;
@@ -169,6 +189,12 @@ const void *nftnl_table_get_data(const struct nftnl_table *t, uint16_t attr,
case NFTNL_TABLE_USE:
*data_len = sizeof(uint32_t);
return &t->use;
+ case NFTNL_TABLE_USERDATA:
+ *data_len = t->user.len;
+ return t->user.data;
+ case NFTNL_TABLE_OWNER:
+ *data_len = sizeof(uint32_t);
+ return &t->owner;
}
return NULL;
}
@@ -216,6 +242,8 @@ void nftnl_table_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ta
mnl_attr_put_u64(nlh, NFTA_TABLE_HANDLE, htobe64(t->handle));
if (t->flags & (1 << NFTNL_TABLE_FLAGS))
mnl_attr_put_u32(nlh, NFTA_TABLE_FLAGS, htonl(t->table_flags));
+ if (t->flags & (1 << NFTNL_TABLE_USERDATA))
+ mnl_attr_put(nlh, NFTA_TABLE_USERDATA, t->user.len, t->user.data);
}
static int nftnl_table_parse_attr_cb(const struct nlattr *attr, void *data)
@@ -237,9 +265,14 @@ static int nftnl_table_parse_attr_cb(const struct nlattr *attr, void *data)
break;
case NFTA_TABLE_FLAGS:
case NFTA_TABLE_USE:
+ case NFTA_TABLE_OWNER:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
abi_breakage();
break;
+ case NFTA_TABLE_USERDATA:
+ if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+ abi_breakage();
+ break;
}
tb[type] = attr;
@@ -251,6 +284,7 @@ int nftnl_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_table *t)
{
struct nlattr *tb[NFTA_TABLE_MAX+1] = {};
struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
+ int ret;
if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_table_parse_attr_cb, tb) < 0)
return -1;
@@ -275,6 +309,17 @@ int nftnl_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_table *t)
t->handle = be64toh(mnl_attr_get_u64(tb[NFTA_TABLE_HANDLE]));
t->flags |= (1 << NFTNL_TABLE_HANDLE);
}
+ if (tb[NFTA_TABLE_USERDATA]) {
+ ret = nftnl_table_set_data(t, NFTNL_TABLE_USERDATA,
+ mnl_attr_get_payload(tb[NFTA_TABLE_USERDATA]),
+ mnl_attr_get_payload_len(tb[NFTA_TABLE_USERDATA]));
+ if (ret < 0)
+ return ret;
+ }
+ if (tb[NFTA_TABLE_OWNER]) {
+ t->owner = ntohl(mnl_attr_get_u32(tb[NFTA_TABLE_OWNER]));
+ t->flags |= (1 << NFTNL_TABLE_OWNER);
+ }
t->family = nfg->nfgen_family;
t->flags |= (1 << NFTNL_TABLE_FAMILY);
@@ -322,23 +367,17 @@ static int nftnl_table_snprintf_default(char *buf, size_t size,
t->table_flags, t->use, (unsigned long long)t->handle);
}
-static int nftnl_table_cmd_snprintf(char *buf, size_t size,
+static int nftnl_table_cmd_snprintf(char *buf, size_t remain,
const struct nftnl_table *t, 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_table_snprintf_default(buf + offset, remain, t);
- SNPRINTF_BUFFER_SIZE(ret, remain, offset);
- break;
- case NFTNL_OUTPUT_XML:
- case NFTNL_OUTPUT_JSON:
- default:
+ if (type != NFTNL_OUTPUT_DEFAULT)
return -1;
- }
+ ret = nftnl_table_snprintf_default(buf + offset, remain, t);
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
return offset;
}
diff --git a/src/udata.c b/src/udata.c
index 0cc3520..e9bfc35 100644
--- a/src/udata.c
+++ b/src/udata.c
@@ -42,6 +42,11 @@ uint32_t nftnl_udata_buf_len(const struct nftnl_udata_buf *buf)
return (uint32_t)(buf->end - buf->data);
}
+static uint32_t nftnl_udata_buf_space(const struct nftnl_udata_buf *buf)
+{
+ return buf->size - nftnl_udata_buf_len(buf);
+}
+
EXPORT_SYMBOL(nftnl_udata_buf_data);
void *nftnl_udata_buf_data(const struct nftnl_udata_buf *buf)
{
@@ -74,7 +79,8 @@ bool nftnl_udata_put(struct nftnl_udata_buf *buf, uint8_t type, uint32_t len,
{
struct nftnl_udata *attr;
- if (len > UINT8_MAX || buf->size < len + sizeof(struct nftnl_udata))
+ if (len > UINT8_MAX ||
+ nftnl_udata_buf_space(buf) < len + sizeof(struct nftnl_udata))
return false;
attr = (struct nftnl_udata *)buf->end;
diff --git a/src/utils.c b/src/utils.c
index 3617837..ffbad89 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -39,146 +39,6 @@ const char *nftnl_family2str(uint32_t family)
return nftnl_family_str[family];
}
-int nftnl_str2family(const char *family)
-{
- int i;
-
- for (i = 0; i < NFPROTO_NUMPROTO; i++) {
- if (nftnl_family_str[i] == NULL)
- continue;
-
- if (strcmp(nftnl_family_str[i], family) == 0)
- return i;
- }
-
- errno = EAFNOSUPPORT;
- return -1;
-}
-
-static struct {
- int len;
- int64_t min;
- uint64_t max;
-} basetype[] = {
- [NFTNL_TYPE_U8] = { .len = sizeof(uint8_t), .max = UINT8_MAX },
- [NFTNL_TYPE_U16] = { .len = sizeof(uint16_t), .max = UINT16_MAX },
- [NFTNL_TYPE_U32] = { .len = sizeof(uint32_t), .max = UINT32_MAX },
- [NFTNL_TYPE_U64] = { .len = sizeof(uint64_t), .max = UINT64_MAX },
- [NFTNL_TYPE_S8] = { .len = sizeof(int8_t), .min = INT8_MIN, .max = INT8_MAX },
- [NFTNL_TYPE_S16] = { .len = sizeof(int16_t), .min = INT16_MIN, .max = INT16_MAX },
- [NFTNL_TYPE_S32] = { .len = sizeof(int32_t), .min = INT32_MIN, .max = INT32_MAX },
- [NFTNL_TYPE_S64] = { .len = sizeof(int64_t), .min = INT64_MIN, .max = INT64_MAX },
-};
-
-int nftnl_get_value(enum nftnl_type type, void *val, void *out)
-{
- union {
- uint8_t u8;
- uint16_t u16;
- uint32_t u32;
- int8_t s8;
- int16_t s16;
- int32_t s32;
- } values;
- void *valuep = NULL;
- int64_t sval;
- uint64_t uval;
-
- switch (type) {
- case NFTNL_TYPE_U8:
- case NFTNL_TYPE_U16:
- case NFTNL_TYPE_U32:
- case NFTNL_TYPE_U64:
- memcpy(&uval, val, sizeof(uval));
- if (uval > basetype[type].max) {
- errno = ERANGE;
- return -1;
- }
- break;
- case NFTNL_TYPE_S8:
- case NFTNL_TYPE_S16:
- case NFTNL_TYPE_S32:
- case NFTNL_TYPE_S64:
- memcpy(&sval, val, sizeof(sval));
- if (sval < basetype[type].min ||
- sval > (int64_t)basetype[type].max) {
- errno = ERANGE;
- return -1;
- }
- break;
- }
-
- switch (type) {
- case NFTNL_TYPE_U8:
- values.u8 = uval;
- valuep = &values.u8;
- break;
- case NFTNL_TYPE_U16:
- values.u16 = uval;
- valuep = &values.u16;
- break;
- case NFTNL_TYPE_U32:
- values.u32 = uval;
- valuep = &values.u32;
- break;
- case NFTNL_TYPE_U64:
- valuep = &uval;
- break;
- case NFTNL_TYPE_S8:
- values.s8 = sval;
- valuep = &values.s8;
- break;
- case NFTNL_TYPE_S16:
- values.s16 = sval;
- valuep = &values.s16;
- break;
- case NFTNL_TYPE_S32:
- values.s32 = sval;
- valuep = &values.s32;
- break;
- case NFTNL_TYPE_S64:
- valuep = &sval;
- break;
- }
- memcpy(out, valuep, basetype[type].len);
- return 0;
-}
-
-int nftnl_strtoi(const char *string, int base, void *out, enum nftnl_type type)
-{
- int ret;
- int64_t sval = 0;
- uint64_t uval = -1;
- char *endptr;
-
- switch (type) {
- case NFTNL_TYPE_U8:
- case NFTNL_TYPE_U16:
- case NFTNL_TYPE_U32:
- case NFTNL_TYPE_U64:
- uval = strtoll(string, &endptr, base);
- ret = nftnl_get_value(type, &uval, out);
- break;
- case NFTNL_TYPE_S8:
- case NFTNL_TYPE_S16:
- case NFTNL_TYPE_S32:
- case NFTNL_TYPE_S64:
- sval = strtoull(string, &endptr, base);
- ret = nftnl_get_value(type, &sval, out);
- break;
- default:
- errno = EINVAL;
- return -1;
- }
-
- if (*endptr) {
- errno = EINVAL;
- return -1;
- }
-
- return ret;
-}
-
const char *nftnl_verdict2str(uint32_t verdict)
{
switch (verdict) {
@@ -209,28 +69,6 @@ const char *nftnl_verdict2str(uint32_t verdict)
}
}
-int nftnl_str2verdict(const char *verdict, int *verdict_num)
-{
- if (strcmp(verdict, "accept") == 0) {
- *verdict_num = NF_ACCEPT;
- return 0;
- } else if (strcmp(verdict, "drop") == 0) {
- *verdict_num = NF_DROP;
- return 0;
- } else if (strcmp(verdict, "return") == 0) {
- *verdict_num = NFT_RETURN;
- return 0;
- } else if (strcmp(verdict, "jump") == 0) {
- *verdict_num = NFT_JUMP;
- return 0;
- } else if (strcmp(verdict, "goto") == 0) {
- *verdict_num = NFT_GOTO;
- return 0;
- }
-
- return -1;
-}
-
enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags)
{
if (flags & NFTNL_OF_EVENT_NEW)
@@ -241,38 +79,6 @@ enum nftnl_cmd_type nftnl_flag2cmd(uint32_t flags)
return NFTNL_CMD_UNSPEC;
}
-static const char *cmd2tag[NFTNL_CMD_MAX] = {
- [NFTNL_CMD_ADD] = "add",
- [NFTNL_CMD_INSERT] = "insert",
- [NFTNL_CMD_DELETE] = "delete",
- [NFTNL_CMD_REPLACE] = "replace",
- [NFTNL_CMD_FLUSH] = "flush",
-};
-
-const char *nftnl_cmd2tag(enum nftnl_cmd_type cmd)
-{
- if (cmd >= NFTNL_CMD_MAX)
- return "unknown";
-
- return cmd2tag[cmd];
-}
-
-uint32_t nftnl_str2cmd(const char *cmd)
-{
- if (strcmp(cmd, "add") == 0)
- return NFTNL_CMD_ADD;
- else if (strcmp(cmd, "insert") == 0)
- return NFTNL_CMD_INSERT;
- else if (strcmp(cmd, "delete") == 0)
- return NFTNL_CMD_DELETE;
- else if (strcmp(cmd, "replace") == 0)
- return NFTNL_CMD_REPLACE;
- else if (strcmp(cmd, "flush") == 0)
- return NFTNL_CMD_FLUSH;
-
- return NFTNL_CMD_UNSPEC;
-}
-
int nftnl_fprintf(FILE *fp, const void *obj, uint32_t cmd, uint32_t type,
uint32_t flags,
int (*snprintf_cb)(char *buf, size_t bufsiz, const void *obj,