@@ -3566,6 +3566,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
3566
3566
[NFTA_SET_OBJ_TYPE ] = { .type = NLA_U32 },
3567
3567
[NFTA_SET_HANDLE ] = { .type = NLA_U64 },
3568
3568
[NFTA_SET_EXPR ] = { .type = NLA_NESTED },
3569
+ [NFTA_SET_EXPRESSIONS ] = { .type = NLA_NESTED },
3569
3570
};
3570
3571
3571
3572
static const struct nla_policy nft_set_desc_policy [NFTA_SET_DESC_MAX + 1 ] = {
@@ -3773,6 +3774,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
3773
3774
u32 portid = ctx -> portid ;
3774
3775
struct nlattr * nest ;
3775
3776
u32 seq = ctx -> seq ;
3777
+ int i ;
3776
3778
3777
3779
event = nfnl_msg_type (NFNL_SUBSYS_NFTABLES , event );
3778
3780
nlh = nlmsg_put (skb , portid , seq , event , sizeof (struct nfgenmsg ),
@@ -3847,6 +3849,17 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
3847
3849
goto nla_put_failure ;
3848
3850
3849
3851
nla_nest_end (skb , nest );
3852
+ } else if (set -> num_exprs > 1 ) {
3853
+ nest = nla_nest_start_noflag (skb , NFTA_SET_EXPRESSIONS );
3854
+ if (nest == NULL )
3855
+ goto nla_put_failure ;
3856
+
3857
+ for (i = 0 ; i < set -> num_exprs ; i ++ ) {
3858
+ if (nft_expr_dump (skb , NFTA_LIST_ELEM ,
3859
+ set -> exprs [i ]) < 0 )
3860
+ goto nla_put_failure ;
3861
+ }
3862
+ nla_nest_end (skb , nest );
3850
3863
}
3851
3864
3852
3865
nlmsg_end (skb , nlh );
@@ -4215,7 +4228,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4215
4228
return err ;
4216
4229
}
4217
4230
4218
- if (nla [NFTA_SET_EXPR ])
4231
+ if (nla [NFTA_SET_EXPR ] || nla [ NFTA_SET_EXPRESSIONS ] )
4219
4232
desc .expr = true;
4220
4233
4221
4234
table = nft_table_lookup (net , nla [NFTA_SET_TABLE ], family , genmask );
@@ -4281,6 +4294,29 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
4281
4294
}
4282
4295
set -> exprs [0 ] = expr ;
4283
4296
set -> num_exprs ++ ;
4297
+ } else if (nla [NFTA_SET_EXPRESSIONS ]) {
4298
+ struct nft_expr * expr ;
4299
+ struct nlattr * tmp ;
4300
+ int left ;
4301
+
4302
+ i = 0 ;
4303
+ nla_for_each_nested (tmp , nla [NFTA_SET_EXPRESSIONS ], left ) {
4304
+ if (i == NFT_SET_EXPR_MAX ) {
4305
+ err = - E2BIG ;
4306
+ goto err_set_init ;
4307
+ }
4308
+ if (nla_type (tmp ) != NFTA_LIST_ELEM ) {
4309
+ err = - EINVAL ;
4310
+ goto err_set_init ;
4311
+ }
4312
+ expr = nft_set_elem_expr_alloc (& ctx , set , tmp );
4313
+ if (IS_ERR (expr )) {
4314
+ err = PTR_ERR (expr );
4315
+ goto err_set_init ;
4316
+ }
4317
+ set -> exprs [i ++ ] = expr ;
4318
+ set -> num_exprs ++ ;
4319
+ }
4284
4320
}
4285
4321
4286
4322
udata = NULL ;
@@ -4540,6 +4576,7 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
4540
4576
[NFTA_SET_ELEM_OBJREF ] = { .type = NLA_STRING ,
4541
4577
.len = NFT_OBJ_MAXNAMELEN - 1 },
4542
4578
[NFTA_SET_ELEM_KEY_END ] = { .type = NLA_NESTED },
4579
+ [NFTA_SET_ELEM_EXPRESSIONS ] = { .type = NLA_NESTED },
4543
4580
};
4544
4581
4545
4582
static const struct nla_policy nft_set_elem_list_policy [NFTA_SET_ELEM_LIST_MAX + 1 ] = {
@@ -4580,6 +4617,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
4580
4617
struct nft_set_elem_expr * elem_expr ;
4581
4618
u32 size , num_exprs = 0 ;
4582
4619
struct nft_expr * expr ;
4620
+ struct nlattr * nest ;
4583
4621
4584
4622
elem_expr = nft_set_ext_expr (ext );
4585
4623
nft_setelem_expr_foreach (expr , elem_expr , size )
@@ -4591,9 +4629,22 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
4591
4629
return -1 ;
4592
4630
4593
4631
return 0 ;
4594
- }
4632
+ } else if (num_exprs > 1 ) {
4633
+ nest = nla_nest_start_noflag (skb , NFTA_SET_ELEM_EXPRESSIONS );
4634
+ if (nest == NULL )
4635
+ goto nla_put_failure ;
4595
4636
4637
+ nft_setelem_expr_foreach (expr , elem_expr , size ) {
4638
+ expr = nft_setelem_expr_at (elem_expr , size );
4639
+ if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr ) < 0 )
4640
+ goto nla_put_failure ;
4641
+ }
4642
+ nla_nest_end (skb , nest );
4643
+ }
4596
4644
return 0 ;
4645
+
4646
+ nla_put_failure :
4647
+ return -1 ;
4597
4648
}
4598
4649
4599
4650
static int nf_tables_fill_setelem (struct sk_buff * skb ,
@@ -5268,7 +5319,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5268
5319
nla [NFTA_SET_ELEM_TIMEOUT ] ||
5269
5320
nla [NFTA_SET_ELEM_EXPIRATION ] ||
5270
5321
nla [NFTA_SET_ELEM_USERDATA ] ||
5271
- nla [NFTA_SET_ELEM_EXPR ]))
5322
+ nla [NFTA_SET_ELEM_EXPR ] ||
5323
+ nla [NFTA_SET_ELEM_EXPRESSIONS ]))
5272
5324
return - EINVAL ;
5273
5325
5274
5326
timeout = 0 ;
@@ -5310,6 +5362,41 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5310
5362
err = - EOPNOTSUPP ;
5311
5363
goto err_set_elem_expr ;
5312
5364
}
5365
+ } else if (nla [NFTA_SET_ELEM_EXPRESSIONS ]) {
5366
+ struct nft_expr * expr ;
5367
+ struct nlattr * tmp ;
5368
+ int left ;
5369
+
5370
+ if (set -> num_exprs == 0 )
5371
+ return - EOPNOTSUPP ;
5372
+
5373
+ i = 0 ;
5374
+ nla_for_each_nested (tmp , nla [NFTA_SET_ELEM_EXPRESSIONS ], left ) {
5375
+ if (i == set -> num_exprs ) {
5376
+ err = - E2BIG ;
5377
+ goto err_set_elem_expr ;
5378
+ }
5379
+ if (nla_type (tmp ) != NFTA_LIST_ELEM ) {
5380
+ err = - EINVAL ;
5381
+ goto err_set_elem_expr ;
5382
+ }
5383
+ expr = nft_set_elem_expr_alloc (ctx , set , tmp );
5384
+ if (IS_ERR (expr )) {
5385
+ err = PTR_ERR (expr );
5386
+ goto err_set_elem_expr ;
5387
+ }
5388
+ expr_array [i ] = expr ;
5389
+
5390
+ if (expr -> ops != set -> exprs [i ]-> ops ) {
5391
+ err = - EOPNOTSUPP ;
5392
+ goto err_set_elem_expr ;
5393
+ }
5394
+ i ++ ;
5395
+ }
5396
+ if (set -> num_exprs != i ) {
5397
+ err = - EOPNOTSUPP ;
5398
+ goto err_set_elem_expr ;
5399
+ }
5313
5400
} else if (set -> num_exprs > 0 ) {
5314
5401
err = nft_set_elem_expr_clone (ctx , set , expr_array );
5315
5402
if (err < 0 )
0 commit comments