mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 12:14:01 +08:00
netfilter: nf_tables: allow to specify stateful expression in set definition
This patch allows users to specify the stateful expression for the elements in this set via NFTA_SET_EXPR. This new feature allows you to turn on counters for all of the elements in this set. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
0c2a85edd1
commit
65038428b2
@ -416,6 +416,7 @@ struct nft_set_type {
|
||||
* @policy: set parameterization (see enum nft_set_policies)
|
||||
* @udlen: user data length
|
||||
* @udata: user data
|
||||
* @expr: stateful expression
|
||||
* @ops: set ops
|
||||
* @flags: set flags
|
||||
* @genmask: generation mask
|
||||
@ -444,6 +445,7 @@ struct nft_set {
|
||||
u16 policy;
|
||||
u16 udlen;
|
||||
unsigned char *udata;
|
||||
struct nft_expr *expr;
|
||||
/* runtime data below here */
|
||||
const struct nft_set_ops *ops ____cacheline_aligned;
|
||||
u16 flags:14,
|
||||
|
@ -342,6 +342,7 @@ enum nft_set_field_attributes {
|
||||
* @NFTA_SET_USERDATA: user data (NLA_BINARY)
|
||||
* @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
|
||||
* @NFTA_SET_HANDLE: set handle (NLA_U64)
|
||||
* @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
|
||||
*/
|
||||
enum nft_set_attributes {
|
||||
NFTA_SET_UNSPEC,
|
||||
@ -361,6 +362,7 @@ enum nft_set_attributes {
|
||||
NFTA_SET_PAD,
|
||||
NFTA_SET_OBJ_TYPE,
|
||||
NFTA_SET_HANDLE,
|
||||
NFTA_SET_EXPR,
|
||||
__NFTA_SET_MAX
|
||||
};
|
||||
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
|
||||
|
@ -3394,6 +3394,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
|
||||
.len = NFT_USERDATA_MAXLEN },
|
||||
[NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
|
||||
[NFTA_SET_HANDLE] = { .type = NLA_U64 },
|
||||
[NFTA_SET_EXPR] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
|
||||
@ -3597,8 +3598,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
{
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nlattr *desc;
|
||||
u32 portid = ctx->portid;
|
||||
struct nlattr *nest;
|
||||
u32 seq = ctx->seq;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
|
||||
@ -3654,9 +3655,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
|
||||
goto nla_put_failure;
|
||||
|
||||
desc = nla_nest_start_noflag(skb, NFTA_SET_DESC);
|
||||
|
||||
if (desc == NULL)
|
||||
nest = nla_nest_start_noflag(skb, NFTA_SET_DESC);
|
||||
if (!nest)
|
||||
goto nla_put_failure;
|
||||
if (set->size &&
|
||||
nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
|
||||
@ -3666,7 +3666,15 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
nf_tables_fill_set_concat(skb, set))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(skb, desc);
|
||||
nla_nest_end(skb, nest);
|
||||
|
||||
if (set->expr) {
|
||||
nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
|
||||
if (nf_tables_fill_expr_info(skb, set->expr) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(skb, nest);
|
||||
}
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return 0;
|
||||
@ -3913,6 +3921,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
const struct nft_set_ops *ops;
|
||||
struct nft_expr *expr = NULL;
|
||||
struct nft_table *table;
|
||||
struct nft_set *set;
|
||||
struct nft_ctx ctx;
|
||||
@ -4069,13 +4078,21 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
name = nla_strdup(nla[NFTA_SET_NAME], GFP_KERNEL);
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto err2;
|
||||
goto err_set_name;
|
||||
}
|
||||
|
||||
err = nf_tables_set_alloc_name(&ctx, set, name);
|
||||
kfree(name);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
goto err_set_alloc_name;
|
||||
|
||||
if (nla[NFTA_SET_EXPR]) {
|
||||
expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
|
||||
if (IS_ERR(expr)) {
|
||||
err = PTR_ERR(expr);
|
||||
goto err_set_alloc_name;
|
||||
}
|
||||
}
|
||||
|
||||
udata = NULL;
|
||||
if (udlen) {
|
||||
@ -4092,6 +4109,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
set->dtype = dtype;
|
||||
set->objtype = objtype;
|
||||
set->dlen = desc.dlen;
|
||||
set->expr = expr;
|
||||
set->flags = flags;
|
||||
set->size = desc.size;
|
||||
set->policy = policy;
|
||||
@ -4107,21 +4125,24 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||
|
||||
err = ops->init(set, &desc, nla);
|
||||
if (err < 0)
|
||||
goto err3;
|
||||
goto err_set_init;
|
||||
|
||||
err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
|
||||
if (err < 0)
|
||||
goto err4;
|
||||
goto err_set_trans;
|
||||
|
||||
list_add_tail_rcu(&set->list, &table->sets);
|
||||
table->use++;
|
||||
return 0;
|
||||
|
||||
err4:
|
||||
err_set_trans:
|
||||
ops->destroy(set);
|
||||
err3:
|
||||
err_set_init:
|
||||
if (expr)
|
||||
nft_expr_destroy(&ctx, expr);
|
||||
err_set_alloc_name:
|
||||
kfree(set->name);
|
||||
err2:
|
||||
err_set_name:
|
||||
kvfree(set);
|
||||
return err;
|
||||
}
|
||||
@ -4131,6 +4152,9 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
if (WARN_ON(set->use > 0))
|
||||
return;
|
||||
|
||||
if (set->expr)
|
||||
nft_expr_destroy(ctx, set->expr);
|
||||
|
||||
set->ops->destroy(set);
|
||||
kfree(set->name);
|
||||
kvfree(set);
|
||||
@ -4982,6 +5006,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
nla[NFTA_SET_ELEM_EXPR]);
|
||||
if (IS_ERR(expr))
|
||||
return PTR_ERR(expr);
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
if (set->expr && set->expr->ops != expr->ops)
|
||||
goto err_set_elem_expr;
|
||||
} else if (set->expr) {
|
||||
expr = kzalloc(set->expr->ops->size, GFP_KERNEL);
|
||||
if (!expr)
|
||||
return -ENOMEM;
|
||||
|
||||
err = nft_expr_clone(expr, set->expr);
|
||||
if (err < 0)
|
||||
goto err_set_elem_expr;
|
||||
}
|
||||
|
||||
err = nft_setelem_parse_key(ctx, set, &elem.key.val,
|
||||
|
Loading…
Reference in New Issue
Block a user