@@ -3394,6 +3394,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
33943394 .len = NFT_USERDATA_MAXLEN },
33953395 [NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
33963396 [NFTA_SET_HANDLE ] = { .type = NLA_U64 },
3397+ [NFTA_SET_EXPR ] = { .type = NLA_NESTED },
33973398};
33983399
33993400static 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,
35973598{
35983599 struct nfgenmsg * nfmsg ;
35993600 struct nlmsghdr * nlh ;
3600- struct nlattr * desc ;
36013601 u32 portid = ctx -> portid ;
3602+ struct nlattr * nest ;
36023603 u32 seq = ctx -> seq ;
36033604
36043605 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,
36543655 if (nla_put (skb , NFTA_SET_USERDATA , set -> udlen , set -> udata ))
36553656 goto nla_put_failure ;
36563657
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 )
36603660 goto nla_put_failure ;
36613661 if (set -> size &&
36623662 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,
36663666 nf_tables_fill_set_concat (skb , set ))
36673667 goto nla_put_failure ;
36683668
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+ }
36703678
36713679 nlmsg_end (skb , nlh );
36723680 return 0 ;
@@ -3913,6 +3921,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
39133921 u8 genmask = nft_genmask_next (net );
39143922 int family = nfmsg -> nfgen_family ;
39153923 const struct nft_set_ops * ops ;
3924+ struct nft_expr * expr = NULL ;
39163925 struct nft_table * table ;
39173926 struct nft_set * set ;
39183927 struct nft_ctx ctx ;
@@ -4069,13 +4078,21 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
40694078 name = nla_strdup (nla [NFTA_SET_NAME ], GFP_KERNEL );
40704079 if (!name ) {
40714080 err = - ENOMEM ;
4072- goto err2 ;
4081+ goto err_set_name ;
40734082 }
40744083
40754084 err = nf_tables_set_alloc_name (& ctx , set , name );
40764085 kfree (name );
40774086 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+ }
40794096
40804097 udata = NULL ;
40814098 if (udlen ) {
@@ -4092,6 +4109,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
40924109 set -> dtype = dtype ;
40934110 set -> objtype = objtype ;
40944111 set -> dlen = desc .dlen ;
4112+ set -> expr = expr ;
40954113 set -> flags = flags ;
40964114 set -> size = desc .size ;
40974115 set -> policy = policy ;
@@ -4107,21 +4125,24 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
41074125
41084126 err = ops -> init (set , & desc , nla );
41094127 if (err < 0 )
4110- goto err3 ;
4128+ goto err_set_init ;
41114129
41124130 err = nft_trans_set_add (& ctx , NFT_MSG_NEWSET , set );
41134131 if (err < 0 )
4114- goto err4 ;
4132+ goto err_set_trans ;
41154133
41164134 list_add_tail_rcu (& set -> list , & table -> sets );
41174135 table -> use ++ ;
41184136 return 0 ;
41194137
4120- err4 :
4138+ err_set_trans :
41214139 ops -> destroy (set );
4122- err3 :
4140+ err_set_init :
4141+ if (expr )
4142+ nft_expr_destroy (& ctx , expr );
4143+ err_set_alloc_name :
41234144 kfree (set -> name );
4124- err2 :
4145+ err_set_name :
41254146 kvfree (set );
41264147 return err ;
41274148}
@@ -4131,6 +4152,9 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
41314152 if (WARN_ON (set -> use > 0 ))
41324153 return ;
41334154
4155+ if (set -> expr )
4156+ nft_expr_destroy (ctx , set -> expr );
4157+
41344158 set -> ops -> destroy (set );
41354159 kfree (set -> name );
41364160 kvfree (set );
@@ -4982,6 +5006,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
49825006 nla [NFTA_SET_ELEM_EXPR ]);
49835007 if (IS_ERR (expr ))
49845008 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 ;
49855021 }
49865022
49875023 err = nft_setelem_parse_key (ctx , set , & elem .key .val ,
0 commit comments