@@ -4977,7 +4977,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
49774977
49784978static int nft_set_elem_expr_dump (struct sk_buff * skb ,
49794979 const struct nft_set * set ,
4980- const struct nft_set_ext * ext )
4980+ const struct nft_set_ext * ext ,
4981+ bool reset )
49814982{
49824983 struct nft_set_elem_expr * elem_expr ;
49834984 u32 size , num_exprs = 0 ;
@@ -4990,7 +4991,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
49904991
49914992 if (num_exprs == 1 ) {
49924993 expr = nft_setelem_expr_at (elem_expr , 0 );
4993- if (nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , expr , false ) < 0 )
4994+ if (nft_expr_dump (skb , NFTA_SET_ELEM_EXPR , expr , reset ) < 0 )
49944995 return -1 ;
49954996
49964997 return 0 ;
@@ -5001,7 +5002,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50015002
50025003 nft_setelem_expr_foreach (expr , elem_expr , size ) {
50035004 expr = nft_setelem_expr_at (elem_expr , size );
5004- if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr , false ) < 0 )
5005+ if (nft_expr_dump (skb , NFTA_LIST_ELEM , expr , reset ) < 0 )
50055006 goto nla_put_failure ;
50065007 }
50075008 nla_nest_end (skb , nest );
@@ -5014,11 +5015,13 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
50145015
50155016static int nf_tables_fill_setelem (struct sk_buff * skb ,
50165017 const struct nft_set * set ,
5017- const struct nft_set_elem * elem )
5018+ const struct nft_set_elem * elem ,
5019+ bool reset )
50185020{
50195021 const struct nft_set_ext * ext = nft_set_elem_ext (set , elem -> priv );
50205022 unsigned char * b = skb_tail_pointer (skb );
50215023 struct nlattr * nest ;
5024+ u64 timeout = 0 ;
50225025
50235026 nest = nla_nest_start_noflag (skb , NFTA_LIST_ELEM );
50245027 if (nest == NULL )
@@ -5041,7 +5044,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50415044 goto nla_put_failure ;
50425045
50435046 if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPRESSIONS ) &&
5044- nft_set_elem_expr_dump (skb , set , ext ))
5047+ nft_set_elem_expr_dump (skb , set , ext , reset ))
50455048 goto nla_put_failure ;
50465049
50475050 if (nft_set_ext_exists (ext , NFT_SET_EXT_OBJREF ) &&
@@ -5054,11 +5057,15 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50545057 htonl (* nft_set_ext_flags (ext ))))
50555058 goto nla_put_failure ;
50565059
5057- if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT ) &&
5058- nla_put_be64 (skb , NFTA_SET_ELEM_TIMEOUT ,
5059- nf_jiffies64_to_msecs (* nft_set_ext_timeout (ext )),
5060- NFTA_SET_ELEM_PAD ))
5061- goto nla_put_failure ;
5060+ if (nft_set_ext_exists (ext , NFT_SET_EXT_TIMEOUT )) {
5061+ timeout = * nft_set_ext_timeout (ext );
5062+ if (nla_put_be64 (skb , NFTA_SET_ELEM_TIMEOUT ,
5063+ nf_jiffies64_to_msecs (timeout ),
5064+ NFTA_SET_ELEM_PAD ))
5065+ goto nla_put_failure ;
5066+ } else if (set -> flags & NFT_SET_TIMEOUT ) {
5067+ timeout = READ_ONCE (set -> timeout );
5068+ }
50625069
50635070 if (nft_set_ext_exists (ext , NFT_SET_EXT_EXPIRATION )) {
50645071 u64 expires , now = get_jiffies_64 ();
@@ -5073,6 +5080,9 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
50735080 nf_jiffies64_to_msecs (expires ),
50745081 NFTA_SET_ELEM_PAD ))
50755082 goto nla_put_failure ;
5083+
5084+ if (reset )
5085+ * nft_set_ext_expiration (ext ) = now + timeout ;
50765086 }
50775087
50785088 if (nft_set_ext_exists (ext , NFT_SET_EXT_USERDATA )) {
@@ -5096,6 +5106,7 @@ struct nft_set_dump_args {
50965106 const struct netlink_callback * cb ;
50975107 struct nft_set_iter iter ;
50985108 struct sk_buff * skb ;
5109+ bool reset ;
50995110};
51005111
51015112static int nf_tables_dump_setelem (const struct nft_ctx * ctx ,
@@ -5106,7 +5117,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
51065117 struct nft_set_dump_args * args ;
51075118
51085119 args = container_of (iter , struct nft_set_dump_args , iter );
5109- return nf_tables_fill_setelem (args -> skb , set , elem );
5120+ return nf_tables_fill_setelem (args -> skb , set , elem , args -> reset );
51105121}
51115122
51125123struct nft_set_dump_ctx {
@@ -5115,7 +5126,7 @@ struct nft_set_dump_ctx {
51155126};
51165127
51175128static int nft_set_catchall_dump (struct net * net , struct sk_buff * skb ,
5118- const struct nft_set * set )
5129+ const struct nft_set * set , bool reset )
51195130{
51205131 struct nft_set_elem_catchall * catchall ;
51215132 u8 genmask = nft_genmask_cur (net );
@@ -5130,7 +5141,7 @@ static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
51305141 continue ;
51315142
51325143 elem .priv = catchall -> elem ;
5133- ret = nf_tables_fill_setelem (skb , set , & elem );
5144+ ret = nf_tables_fill_setelem (skb , set , & elem , reset );
51345145 break ;
51355146 }
51365147
@@ -5148,6 +5159,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
51485159 bool set_found = false;
51495160 struct nlmsghdr * nlh ;
51505161 struct nlattr * nest ;
5162+ bool reset = false;
51515163 u32 portid , seq ;
51525164 int event ;
51535165
@@ -5195,8 +5207,12 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
51955207 if (nest == NULL )
51965208 goto nla_put_failure ;
51975209
5210+ if (NFNL_MSG_TYPE (cb -> nlh -> nlmsg_type ) == NFT_MSG_GETSETELEM_RESET )
5211+ reset = true;
5212+
51985213 args .cb = cb ;
51995214 args .skb = skb ;
5215+ args .reset = reset ;
52005216 args .iter .genmask = nft_genmask_cur (net );
52015217 args .iter .skip = cb -> args [0 ];
52025218 args .iter .count = 0 ;
@@ -5205,7 +5221,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
52055221 set -> ops -> walk (& dump_ctx -> ctx , set , & args .iter );
52065222
52075223 if (!args .iter .err && args .iter .count == cb -> args [0 ])
5208- args .iter .err = nft_set_catchall_dump (net , skb , set );
5224+ args .iter .err = nft_set_catchall_dump (net , skb , set , reset );
52095225 rcu_read_unlock ();
52105226
52115227 nla_nest_end (skb , nest );
@@ -5243,7 +5259,8 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
52435259 const struct nft_ctx * ctx , u32 seq ,
52445260 u32 portid , int event , u16 flags ,
52455261 const struct nft_set * set ,
5246- const struct nft_set_elem * elem )
5262+ const struct nft_set_elem * elem ,
5263+ bool reset )
52475264{
52485265 struct nlmsghdr * nlh ;
52495266 struct nlattr * nest ;
@@ -5264,7 +5281,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
52645281 if (nest == NULL )
52655282 goto nla_put_failure ;
52665283
5267- err = nf_tables_fill_setelem (skb , set , elem );
5284+ err = nf_tables_fill_setelem (skb , set , elem , reset );
52685285 if (err < 0 )
52695286 goto nla_put_failure ;
52705287
@@ -5384,7 +5401,7 @@ static int nft_setelem_get(struct nft_ctx *ctx, struct nft_set *set,
53845401}
53855402
53865403static int nft_get_set_elem (struct nft_ctx * ctx , struct nft_set * set ,
5387- const struct nlattr * attr )
5404+ const struct nlattr * attr , bool reset )
53885405{
53895406 struct nlattr * nla [NFTA_SET_ELEM_MAX + 1 ];
53905407 struct nft_set_elem elem ;
@@ -5428,7 +5445,8 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
54285445 return err ;
54295446
54305447 err = nf_tables_fill_setelem_info (skb , ctx , ctx -> seq , ctx -> portid ,
5431- NFT_MSG_NEWSETELEM , 0 , set , & elem );
5448+ NFT_MSG_NEWSETELEM , 0 , set , & elem ,
5449+ reset );
54325450 if (err < 0 )
54335451 goto err_fill_setelem ;
54345452
@@ -5452,6 +5470,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
54525470 struct nft_set * set ;
54535471 struct nlattr * attr ;
54545472 struct nft_ctx ctx ;
5473+ bool reset = false;
54555474 int rem , err = 0 ;
54565475
54575476 table = nft_table_lookup (net , nla [NFTA_SET_ELEM_LIST_TABLE ], family ,
@@ -5486,8 +5505,11 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
54865505 if (!nla [NFTA_SET_ELEM_LIST_ELEMENTS ])
54875506 return - EINVAL ;
54885507
5508+ if (NFNL_MSG_TYPE (info -> nlh -> nlmsg_type ) == NFT_MSG_GETSETELEM_RESET )
5509+ reset = true;
5510+
54895511 nla_for_each_nested (attr , nla [NFTA_SET_ELEM_LIST_ELEMENTS ], rem ) {
5490- err = nft_get_set_elem (& ctx , set , attr );
5512+ err = nft_get_set_elem (& ctx , set , attr , reset );
54915513 if (err < 0 ) {
54925514 NL_SET_BAD_ATTR (extack , attr );
54935515 break ;
@@ -5520,7 +5542,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
55205542 flags |= ctx -> flags & (NLM_F_CREATE | NLM_F_EXCL );
55215543
55225544 err = nf_tables_fill_setelem_info (skb , ctx , 0 , portid , event , flags ,
5523- set , elem );
5545+ set , elem , false );
55245546 if (err < 0 ) {
55255547 kfree_skb (skb );
55265548 goto err ;
@@ -8396,6 +8418,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83968418 .attr_count = NFTA_SET_ELEM_LIST_MAX ,
83978419 .policy = nft_set_elem_list_policy ,
83988420 },
8421+ [NFT_MSG_GETSETELEM_RESET ] = {
8422+ .call = nf_tables_getsetelem ,
8423+ .type = NFNL_CB_RCU ,
8424+ .attr_count = NFTA_SET_ELEM_LIST_MAX ,
8425+ .policy = nft_set_elem_list_policy ,
8426+ },
83998427 [NFT_MSG_DELSETELEM ] = {
84008428 .call = nf_tables_delsetelem ,
84018429 .type = NFNL_CB_BATCH ,
0 commit comments