@@ -4496,8 +4496,8 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
44964496 [NFT_SET_EXT_DATA ] = {
44974497 .align = __alignof__(u32 ),
44984498 },
4499- [NFT_SET_EXT_EXPR ] = {
4500- .align = __alignof__(struct nft_expr ),
4499+ [NFT_SET_EXT_EXPRESSIONS ] = {
4500+ .align = __alignof__(struct nft_set_elem_expr ),
45014501 },
45024502 [NFT_SET_EXT_OBJREF ] = {
45034503 .len = sizeof (struct nft_object * ),
@@ -4573,6 +4573,29 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
45734573 return 0 ;
45744574}
45754575
4576+ static int nft_set_elem_expr_dump (struct sk_buff * skb ,
4577+ const struct nft_set * set ,
4578+ const struct nft_set_ext * ext )
4579+ {
4580+ struct nft_set_elem_expr * elem_expr ;
4581+ u32 size , num_exprs = 0 ;
4582+ struct nft_expr * expr ;
4583+
4584+ elem_expr = nft_set_ext_expr (ext );
4585+ nft_setelem_expr_foreach (expr , elem_expr , size )
4586+ num_exprs ++ ;
4587+
4588+ if (num_exprs == 1 ) {
4589+ expr = nft_setelem_expr_at (elem_expr , 0 );
4590+ if (nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , expr ) < 0 )
4591+ return -1 ;
4592+
4593+ return 0 ;
4594+ }
4595+
4596+ return 0 ;
4597+ }
4598+
45764599static int nf_tables_fill_setelem (struct sk_buff * skb ,
45774600 const struct nft_set * set ,
45784601 const struct nft_set_elem * elem )
@@ -4600,8 +4623,8 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
46004623 set -> dlen ) < 0 )
46014624 goto nla_put_failure ;
46024625
4603- if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ) &&
4604- nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , nft_set_ext_expr ( ext )) < 0 )
4626+ if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ) &&
4627+ nft_set_elem_expr_dump (skb , set , ext ))
46054628 goto nla_put_failure ;
46064629
46074630 if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
@@ -5096,8 +5119,8 @@ void *nft_set_elem_init(const struct nft_set *set,
50965119 return elem ;
50975120}
50985121
5099- static void nft_set_elem_expr_destroy (const struct nft_ctx * ctx ,
5100- struct nft_expr * expr )
5122+ static void __nft_set_elem_expr_destroy (const struct nft_ctx * ctx ,
5123+ struct nft_expr * expr )
51015124{
51025125 if (expr -> ops -> destroy_clone ) {
51035126 expr -> ops -> destroy_clone (ctx , expr );
@@ -5107,6 +5130,16 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
51075130 }
51085131}
51095132
5133+ static void nft_set_elem_expr_destroy (const struct nft_ctx * ctx ,
5134+ struct nft_set_elem_expr * elem_expr )
5135+ {
5136+ struct nft_expr * expr ;
5137+ u32 size ;
5138+
5139+ nft_setelem_expr_foreach (expr , elem_expr , size )
5140+ __nft_set_elem_expr_destroy (ctx , expr );
5141+ }
5142+
51105143void nft_set_elem_destroy (const struct nft_set * set , void * elem ,
51115144 bool destroy_expr )
51125145{
@@ -5119,7 +5152,7 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
51195152 nft_data_release (nft_set_ext_key (ext ), NFT_DATA_VALUE );
51205153 if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
51215154 nft_data_release (nft_set_ext_data (ext ), set -> dtype );
5122- if (destroy_expr && nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ))
5155+ if (destroy_expr && nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ))
51235156 nft_set_elem_expr_destroy (& ctx , nft_set_ext_expr (ext ));
51245157
51255158 if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ))
@@ -5136,7 +5169,7 @@ static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
51365169{
51375170 struct nft_set_ext * ext = nft_set_elem_ext (set , elem );
51385171
5139- if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ))
5172+ if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ))
51405173 nft_set_elem_expr_destroy (ctx , nft_set_ext_expr (ext ));
51415174
51425175 kfree (elem );
@@ -5171,6 +5204,18 @@ static int nft_set_elem_expr_clone(const struct nft_ctx *ctx,
51715204 return - ENOMEM ;
51725205}
51735206
5207+ static void nft_set_elem_expr_setup (const struct nft_set_ext * ext , int i ,
5208+ struct nft_expr * expr_array [])
5209+ {
5210+ struct nft_set_elem_expr * elem_expr = nft_set_ext_expr (ext );
5211+ struct nft_expr * expr = nft_setelem_expr_at (elem_expr , elem_expr -> size );
5212+
5213+ memcpy (expr , expr_array [i ], expr_array [i ]-> ops -> size );
5214+ elem_expr -> size += expr_array [i ]-> ops -> size ;
5215+ kfree (expr_array [i ]);
5216+ expr_array [i ] = NULL ;
5217+ }
5218+
51745219static int nft_add_set_elem (struct nft_ctx * ctx , struct nft_set * set ,
51755220 const struct nlattr * attr , u32 nlmsg_flags )
51765221{
@@ -5186,11 +5231,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
51865231 struct nft_data_desc desc ;
51875232 enum nft_registers dreg ;
51885233 struct nft_trans * trans ;
5189- u32 flags = 0 ;
5234+ u32 flags = 0 , size = 0 ;
51905235 u64 timeout ;
51915236 u64 expiration ;
5192- u8 ulen ;
51935237 int err , i ;
5238+ u8 ulen ;
51945239
51955240 err = nla_parse_nested_deprecated (nla , NFTA_SET_ELEM_MAX , attr ,
51965241 nft_set_elem_policy , NULL );
@@ -5293,9 +5338,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
52935338 nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
52945339 }
52955340
5296- if (set -> num_exprs == 1 )
5297- nft_set_ext_add_length (& tmpl , NFT_SET_EXT_EXPR ,
5298- expr_array [0 ]-> ops -> size );
5341+ if (set -> num_exprs ) {
5342+ for (i = 0 ; i < set -> num_exprs ; i ++ )
5343+ size += expr_array [i ]-> ops -> size ;
5344+
5345+ nft_set_ext_add_length (& tmpl , NFT_SET_EXT_EXPRESSIONS ,
5346+ sizeof (struct nft_set_elem_expr ) +
5347+ size );
5348+ }
52995349
53005350 if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
53015351 if (!(set -> flags & NFT_SET_OBJECT )) {
@@ -5377,13 +5427,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
53775427 * nft_set_ext_obj (ext ) = obj ;
53785428 obj -> use ++ ;
53795429 }
5380- if (set -> num_exprs == 1 ) {
5381- struct nft_expr * expr = expr_array [0 ];
5382-
5383- memcpy (nft_set_ext_expr (ext ), expr , expr -> ops -> size );
5384- kfree (expr );
5385- expr_array [0 ] = NULL ;
5386- }
5430+ for (i = 0 ; i < set -> num_exprs ; i ++ )
5431+ nft_set_elem_expr_setup (ext , i , expr_array );
53875432
53885433 trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
53895434 if (trans == NULL )
0 commit comments