@@ -4496,8 +4496,8 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
4496
4496
[NFT_SET_EXT_DATA ] = {
4497
4497
.align = __alignof__(u32 ),
4498
4498
},
4499
- [NFT_SET_EXT_EXPR ] = {
4500
- .align = __alignof__(struct nft_expr ),
4499
+ [NFT_SET_EXT_EXPRESSIONS ] = {
4500
+ .align = __alignof__(struct nft_set_elem_expr ),
4501
4501
},
4502
4502
[NFT_SET_EXT_OBJREF ] = {
4503
4503
.len = sizeof (struct nft_object * ),
@@ -4573,6 +4573,29 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
4573
4573
return 0 ;
4574
4574
}
4575
4575
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
+
4576
4599
static int nf_tables_fill_setelem (struct sk_buff * skb ,
4577
4600
const struct nft_set * set ,
4578
4601
const struct nft_set_elem * elem )
@@ -4600,8 +4623,8 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
4600
4623
set -> dlen ) < 0 )
4601
4624
goto nla_put_failure ;
4602
4625
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 ))
4605
4628
goto nla_put_failure ;
4606
4629
4607
4630
if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
@@ -5096,8 +5119,8 @@ void *nft_set_elem_init(const struct nft_set *set,
5096
5119
return elem ;
5097
5120
}
5098
5121
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 )
5101
5124
{
5102
5125
if (expr -> ops -> destroy_clone ) {
5103
5126
expr -> ops -> destroy_clone (ctx , expr );
@@ -5107,6 +5130,16 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
5107
5130
}
5108
5131
}
5109
5132
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
+
5110
5143
void nft_set_elem_destroy (const struct nft_set * set , void * elem ,
5111
5144
bool destroy_expr )
5112
5145
{
@@ -5119,7 +5152,7 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
5119
5152
nft_data_release (nft_set_ext_key (ext ), NFT_DATA_VALUE );
5120
5153
if (nft_set_ext_exists (ext , NFT_SET_EXT_DATA ))
5121
5154
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 ))
5123
5156
nft_set_elem_expr_destroy (& ctx , nft_set_ext_expr (ext ));
5124
5157
5125
5158
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,
5136
5169
{
5137
5170
struct nft_set_ext * ext = nft_set_elem_ext (set , elem );
5138
5171
5139
- if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPR ))
5172
+ if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ))
5140
5173
nft_set_elem_expr_destroy (ctx , nft_set_ext_expr (ext ));
5141
5174
5142
5175
kfree (elem );
@@ -5171,6 +5204,18 @@ static int nft_set_elem_expr_clone(const struct nft_ctx *ctx,
5171
5204
return - ENOMEM ;
5172
5205
}
5173
5206
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
+
5174
5219
static int nft_add_set_elem (struct nft_ctx * ctx , struct nft_set * set ,
5175
5220
const struct nlattr * attr , u32 nlmsg_flags )
5176
5221
{
@@ -5186,11 +5231,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5186
5231
struct nft_data_desc desc ;
5187
5232
enum nft_registers dreg ;
5188
5233
struct nft_trans * trans ;
5189
- u32 flags = 0 ;
5234
+ u32 flags = 0 , size = 0 ;
5190
5235
u64 timeout ;
5191
5236
u64 expiration ;
5192
- u8 ulen ;
5193
5237
int err , i ;
5238
+ u8 ulen ;
5194
5239
5195
5240
err = nla_parse_nested_deprecated (nla , NFTA_SET_ELEM_MAX , attr ,
5196
5241
nft_set_elem_policy , NULL );
@@ -5293,9 +5338,14 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5293
5338
nft_set_ext_add (& tmpl , NFT_SET_EXT_TIMEOUT );
5294
5339
}
5295
5340
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
+ }
5299
5349
5300
5350
if (nla [NFTA_SET_ELEM_OBJREF ] != NULL ) {
5301
5351
if (!(set -> flags & NFT_SET_OBJECT )) {
@@ -5377,13 +5427,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5377
5427
* nft_set_ext_obj (ext ) = obj ;
5378
5428
obj -> use ++ ;
5379
5429
}
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 );
5387
5432
5388
5433
trans = nft_trans_elem_alloc (ctx , NFT_MSG_NEWSETELEM , set );
5389
5434
if (trans == NULL )
0 commit comments