@@ -5229,7 +5229,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
5229
5229
5230
5230
static int nft_set_elem_expr_dump (struct sk_buff * skb ,
5231
5231
const struct nft_set * set ,
5232
- const struct nft_set_ext * ext )
5232
+ const struct nft_set_ext * ext ,
5233
+ bool reset )
5233
5234
{
5234
5235
struct nft_set_elem_expr * elem_expr ;
5235
5236
u32 size , num_exprs = 0 ;
@@ -5242,7 +5243,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
5242
5243
5243
5244
if (num_exprs == 1 ) {
5244
5245
expr = nft_setelem_expr_at (elem_expr , 0 );
5245
- if (nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , expr , false ) < 0 )
5246
+ if (nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , expr , reset ) < 0 )
5246
5247
return -1 ;
5247
5248
5248
5249
return 0 ;
@@ -5253,7 +5254,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
5253
5254
5254
5255
nft_setelem_expr_foreach (expr , elem_expr , size ) {
5255
5256
expr = nft_setelem_expr_at (elem_expr , size );
5256
- if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr , false ) < 0 )
5257
+ if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr , reset ) < 0 )
5257
5258
goto nla_put_failure ;
5258
5259
}
5259
5260
nla_nest_end (skb , nest );
@@ -5266,11 +5267,13 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
5266
5267
5267
5268
static int nf_tables_fill_setelem (struct sk_buff * skb ,
5268
5269
const struct nft_set * set ,
5269
- const struct nft_set_elem * elem )
5270
+ const struct nft_set_elem * elem ,
5271
+ bool reset )
5270
5272
{
5271
5273
const struct nft_set_ext * ext = nft_set_elem_ext (set , elem -> priv );
5272
5274
unsigned char * b = skb_tail_pointer (skb );
5273
5275
struct nlattr * nest ;
5276
+ u64 timeout = 0 ;
5274
5277
5275
5278
nest = nla_nest_start_noflag (skb , NFTA_LIST_ELEM );
5276
5279
if (nest == NULL )
@@ -5293,7 +5296,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
5293
5296
goto nla_put_failure ;
5294
5297
5295
5298
if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ) &&
5296
- nft_set_elem_expr_dump (skb , set , ext ))
5299
+ nft_set_elem_expr_dump (skb , set , ext , reset ))
5297
5300
goto nla_put_failure ;
5298
5301
5299
5302
if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
@@ -5306,11 +5309,15 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
5306
5309
htonl (* nft_set_ext_flags (ext ))))
5307
5310
goto nla_put_failure ;
5308
5311
5309
- if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT ) &&
5310
- nla_put_be64 (skb , NFTA_SET_ELEM_TIMEOUT ,
5311
- nf_jiffies64_to_msecs (* nft_set_ext_timeout (ext )),
5312
- NFTA_SET_ELEM_PAD ))
5313
- goto nla_put_failure ;
5312
+ if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT )) {
5313
+ timeout = * nft_set_ext_timeout (ext );
5314
+ if (nla_put_be64 (skb , NFTA_SET_ELEM_TIMEOUT ,
5315
+ nf_jiffies64_to_msecs (timeout ),
5316
+ NFTA_SET_ELEM_PAD ))
5317
+ goto nla_put_failure ;
5318
+ } else if (set -> flags & NFT_SET_TIMEOUT ) {
5319
+ timeout = READ_ONCE (set -> timeout );
5320
+ }
5314
5321
5315
5322
if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPIRATION )) {
5316
5323
u64 expires , now = get_jiffies_64 ();
@@ -5325,6 +5332,9 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
5325
5332
nf_jiffies64_to_msecs (expires ),
5326
5333
NFTA_SET_ELEM_PAD ))
5327
5334
goto nla_put_failure ;
5335
+
5336
+ if (reset )
5337
+ * nft_set_ext_expiration (ext ) = now + timeout ;
5328
5338
}
5329
5339
5330
5340
if (nft_set_ext_exists (ext , NFT_SET_EXT_USERDATA )) {
@@ -5348,6 +5358,7 @@ struct nft_set_dump_args {
5348
5358
const struct netlink_callback * cb ;
5349
5359
struct nft_set_iter iter ;
5350
5360
struct sk_buff * skb ;
5361
+ bool reset ;
5351
5362
};
5352
5363
5353
5364
static int nf_tables_dump_setelem (const struct nft_ctx * ctx ,
@@ -5358,7 +5369,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
5358
5369
struct nft_set_dump_args * args ;
5359
5370
5360
5371
args = container_of (iter , struct nft_set_dump_args , iter );
5361
- return nf_tables_fill_setelem (args -> skb , set , elem );
5372
+ return nf_tables_fill_setelem (args -> skb , set , elem , args -> reset );
5362
5373
}
5363
5374
5364
5375
struct nft_set_dump_ctx {
@@ -5367,7 +5378,7 @@ struct nft_set_dump_ctx {
5367
5378
};
5368
5379
5369
5380
static int nft_set_catchall_dump (struct net * net , struct sk_buff * skb ,
5370
- const struct nft_set * set )
5381
+ const struct nft_set * set , bool reset )
5371
5382
{
5372
5383
struct nft_set_elem_catchall * catchall ;
5373
5384
u8 genmask = nft_genmask_cur (net );
@@ -5382,7 +5393,7 @@ static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
5382
5393
continue ;
5383
5394
5384
5395
elem .priv = catchall -> elem ;
5385
- ret = nf_tables_fill_setelem (skb , set , & elem );
5396
+ ret = nf_tables_fill_setelem (skb , set , & elem , reset );
5386
5397
break ;
5387
5398
}
5388
5399
@@ -5400,6 +5411,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
5400
5411
bool set_found = false;
5401
5412
struct nlmsghdr * nlh ;
5402
5413
struct nlattr * nest ;
5414
+ bool reset = false;
5403
5415
u32 portid , seq ;
5404
5416
int event ;
5405
5417
@@ -5447,8 +5459,12 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
5447
5459
if (nest == NULL )
5448
5460
goto nla_put_failure ;
5449
5461
5462
+ if (NFNL_MSG_TYPE (cb -> nlh -> nlmsg_type ) == NFT_MSG_GETSETELEM_RESET )
5463
+ reset = true;
5464
+
5450
5465
args .cb = cb ;
5451
5466
args .skb = skb ;
5467
+ args .reset = reset ;
5452
5468
args .iter .genmask = nft_genmask_cur (net );
5453
5469
args .iter .skip = cb -> args [0 ];
5454
5470
args .iter .count = 0 ;
@@ -5457,7 +5473,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
5457
5473
set -> ops -> walk (& dump_ctx -> ctx , set , & args .iter );
5458
5474
5459
5475
if (!args .iter .err && args .iter .count == cb -> args [0 ])
5460
- args .iter .err = nft_set_catchall_dump (net , skb , set );
5476
+ args .iter .err = nft_set_catchall_dump (net , skb , set , reset );
5461
5477
rcu_read_unlock ();
5462
5478
5463
5479
nla_nest_end (skb , nest );
@@ -5495,7 +5511,8 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
5495
5511
const struct nft_ctx * ctx , u32 seq ,
5496
5512
u32 portid , int event , u16 flags ,
5497
5513
const struct nft_set * set ,
5498
- const struct nft_set_elem * elem )
5514
+ const struct nft_set_elem * elem ,
5515
+ bool reset )
5499
5516
{
5500
5517
struct nlmsghdr * nlh ;
5501
5518
struct nlattr * nest ;
@@ -5516,7 +5533,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
5516
5533
if (nest == NULL )
5517
5534
goto nla_put_failure ;
5518
5535
5519
- err = nf_tables_fill_setelem (skb , set , elem );
5536
+ err = nf_tables_fill_setelem (skb , set , elem , reset );
5520
5537
if (err < 0 )
5521
5538
goto nla_put_failure ;
5522
5539
@@ -5622,7 +5639,7 @@ static int nft_setelem_get(struct nft_ctx *ctx, struct nft_set *set,
5622
5639
}
5623
5640
5624
5641
static int nft_get_set_elem (struct nft_ctx * ctx , struct nft_set * set ,
5625
- const struct nlattr * attr )
5642
+ const struct nlattr * attr , bool reset )
5626
5643
{
5627
5644
struct nlattr * nla [NFTA_SET_ELEM_MAX + 1 ];
5628
5645
struct nft_set_elem elem ;
@@ -5666,7 +5683,8 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5666
5683
return err ;
5667
5684
5668
5685
err = nf_tables_fill_setelem_info (skb , ctx , ctx -> seq , ctx -> portid ,
5669
- NFT_MSG_NEWSETELEM , 0 , set , & elem );
5686
+ NFT_MSG_NEWSETELEM , 0 , set , & elem ,
5687
+ reset );
5670
5688
if (err < 0 )
5671
5689
goto err_fill_setelem ;
5672
5690
@@ -5690,6 +5708,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
5690
5708
struct nft_set * set ;
5691
5709
struct nlattr * attr ;
5692
5710
struct nft_ctx ctx ;
5711
+ bool reset = false;
5693
5712
int rem , err = 0 ;
5694
5713
5695
5714
table = nft_table_lookup (net , nla [NFTA_SET_ELEM_LIST_TABLE ], family ,
@@ -5724,8 +5743,11 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
5724
5743
if (!nla [NFTA_SET_ELEM_LIST_ELEMENTS ])
5725
5744
return - EINVAL ;
5726
5745
5746
+ if (NFNL_MSG_TYPE (info -> nlh -> nlmsg_type ) == NFT_MSG_GETSETELEM_RESET )
5747
+ reset = true;
5748
+
5727
5749
nla_for_each_nested (attr , nla [NFTA_SET_ELEM_LIST_ELEMENTS ], rem ) {
5728
- err = nft_get_set_elem (& ctx , set , attr );
5750
+ err = nft_get_set_elem (& ctx , set , attr , reset );
5729
5751
if (err < 0 ) {
5730
5752
NL_SET_BAD_ATTR (extack , attr );
5731
5753
break ;
@@ -5758,7 +5780,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
5758
5780
flags |= ctx -> flags & (NLM_F_CREATE | NLM_F_EXCL );
5759
5781
5760
5782
err = nf_tables_fill_setelem_info (skb , ctx , 0 , portid , event , flags ,
5761
- set , elem );
5783
+ set , elem , false );
5762
5784
if (err < 0 ) {
5763
5785
kfree_skb (skb );
5764
5786
goto err ;
@@ -8715,6 +8737,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
8715
8737
.attr_count = NFTA_SET_ELEM_LIST_MAX ,
8716
8738
.policy = nft_set_elem_list_policy ,
8717
8739
},
8740
+ [NFT_MSG_GETSETELEM_RESET ] = {
8741
+ .call = nf_tables_getsetelem ,
8742
+ .type = NFNL_CB_RCU ,
8743
+ .attr_count = NFTA_SET_ELEM_LIST_MAX ,
8744
+ .policy = nft_set_elem_list_policy ,
8745
+ },
8718
8746
[NFT_MSG_DELSETELEM ] = {
8719
8747
.call = nf_tables_delsetelem ,
8720
8748
.type = NFNL_CB_BATCH ,
0 commit comments