@@ -3394,6 +3394,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
3394
3394
.len = NFT_USERDATA_MAXLEN },
3395
3395
[NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
3396
3396
[NFTA_SET_HANDLE ] = { .type = NLA_U64 },
3397
+ [NFTA_SET_EXPR ] = { .type = NLA_NESTED },
3397
3398
};
3398
3399
3399
3400
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,
3597
3598
{
3598
3599
struct nfgenmsg * nfmsg ;
3599
3600
struct nlmsghdr * nlh ;
3600
- struct nlattr * desc ;
3601
3601
u32 portid = ctx -> portid ;
3602
+ struct nlattr * nest ;
3602
3603
u32 seq = ctx -> seq ;
3603
3604
3604
3605
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,
3654
3655
if (nla_put (skb , NFTA_SET_USERDATA , set -> udlen , set -> udata ))
3655
3656
goto nla_put_failure ;
3656
3657
3657
- desc = nla_nest_start_noflag (skb , NFTA_SET_DESC );
3658
-
3659
- if (desc == NULL )
3658
+ nest = nla_nest_start_noflag (skb , NFTA_SET_DESC );
3659
+ if (!nest )
3660
3660
goto nla_put_failure ;
3661
3661
if (set -> size &&
3662
3662
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,
3666
3666
nf_tables_fill_set_concat (skb , set ))
3667
3667
goto nla_put_failure ;
3668
3668
3669
- nla_nest_end (skb , desc );
3669
+ nla_nest_end (skb , nest );
3670
+
3671
+ if (set -> expr ) {
3672
+ nest = nla_nest_start_noflag (skb , NFTA_SET_EXPR );
3673
+ if (nf_tables_fill_expr_info (skb , set -> expr ) < 0 )
3674
+ goto nla_put_failure ;
3675
+
3676
+ nla_nest_end (skb , nest );
3677
+ }
3670
3678
3671
3679
nlmsg_end (skb , nlh );
3672
3680
return 0 ;
@@ -3913,6 +3921,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
3913
3921
u8 genmask = nft_genmask_next (net );
3914
3922
int family = nfmsg -> nfgen_family ;
3915
3923
const struct nft_set_ops * ops ;
3924
+ struct nft_expr * expr = NULL ;
3916
3925
struct nft_table * table ;
3917
3926
struct nft_set * set ;
3918
3927
struct nft_ctx ctx ;
@@ -4069,13 +4078,21 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4069
4078
name = nla_strdup (nla [NFTA_SET_NAME ], GFP_KERNEL );
4070
4079
if (!name ) {
4071
4080
err = - ENOMEM ;
4072
- goto err2 ;
4081
+ goto err_set_name ;
4073
4082
}
4074
4083
4075
4084
err = nf_tables_set_alloc_name (& ctx , set , name );
4076
4085
kfree (name );
4077
4086
if (err < 0 )
4078
- goto err2 ;
4087
+ goto err_set_alloc_name ;
4088
+
4089
+ if (nla [NFTA_SET_EXPR ]) {
4090
+ expr = nft_set_elem_expr_alloc (& ctx , set , nla [NFTA_SET_EXPR ]);
4091
+ if (IS_ERR (expr )) {
4092
+ err = PTR_ERR (expr );
4093
+ goto err_set_alloc_name ;
4094
+ }
4095
+ }
4079
4096
4080
4097
udata = NULL ;
4081
4098
if (udlen ) {
@@ -4092,6 +4109,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4092
4109
set -> dtype = dtype ;
4093
4110
set -> objtype = objtype ;
4094
4111
set -> dlen = desc .dlen ;
4112
+ set -> expr = expr ;
4095
4113
set -> flags = flags ;
4096
4114
set -> size = desc .size ;
4097
4115
set -> policy = policy ;
@@ -4107,21 +4125,24 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4107
4125
4108
4126
err = ops -> init (set , & desc , nla );
4109
4127
if (err < 0 )
4110
- goto err3 ;
4128
+ goto err_set_init ;
4111
4129
4112
4130
err = nft_trans_set_add (& ctx , NFT_MSG_NEWSET , set );
4113
4131
if (err < 0 )
4114
- goto err4 ;
4132
+ goto err_set_trans ;
4115
4133
4116
4134
list_add_tail_rcu (& set -> list , & table -> sets );
4117
4135
table -> use ++ ;
4118
4136
return 0 ;
4119
4137
4120
- err4 :
4138
+ err_set_trans :
4121
4139
ops -> destroy (set );
4122
- err3 :
4140
+ err_set_init :
4141
+ if (expr )
4142
+ nft_expr_destroy (& ctx , expr );
4143
+ err_set_alloc_name :
4123
4144
kfree (set -> name );
4124
- err2 :
4145
+ err_set_name :
4125
4146
kvfree (set );
4126
4147
return err ;
4127
4148
}
@@ -4131,6 +4152,9 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
4131
4152
if (WARN_ON (set -> use > 0 ))
4132
4153
return ;
4133
4154
4155
+ if (set -> expr )
4156
+ nft_expr_destroy (ctx , set -> expr );
4157
+
4134
4158
set -> ops -> destroy (set );
4135
4159
kfree (set -> name );
4136
4160
kvfree (set );
@@ -4982,6 +5006,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4982
5006
nla [NFTA_SET_ELEM_EXPR ]);
4983
5007
if (IS_ERR (expr ))
4984
5008
return PTR_ERR (expr );
5009
+
5010
+ err = - EOPNOTSUPP ;
5011
+ if (set -> expr && set -> expr -> ops != expr -> ops )
5012
+ goto err_set_elem_expr ;
5013
+ } else if (set -> expr ) {
5014
+ expr = kzalloc (set -> expr -> ops -> size , GFP_KERNEL );
5015
+ if (!expr )
5016
+ return - ENOMEM ;
5017
+
5018
+ err = nft_expr_clone (expr , set -> expr );
5019
+ if (err < 0 )
5020
+ goto err_set_elem_expr ;
4985
5021
}
4986
5022
4987
5023
err = nft_setelem_parse_key (ctx , set , & elem .key .val ,
0 commit comments