Skip to content

Commit 079cd63

Browse files
Phil Sutterummakynes
authored andcommitted
netfilter: nf_tables: Introduce NFT_MSG_GETSETELEM_RESET
Analogous to NFT_MSG_GETOBJ_RESET, but for set elements with a timeout or attached stateful expressions like counters or quotas - reset them all at once. Respect a per element timeout value if present to reset the 'expires' value to. Signed-off-by: Phil Sutter <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 4589725 commit 079cd63

File tree

2 files changed

+50
-20
lines changed

2 files changed

+50
-20
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ enum nft_verdicts {
105105
* @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
106106
* @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
107107
* @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
108+
* @NFT_MSG_GETSETELEM_RESET: get set elements and reset attached stateful expressions (enum nft_set_elem_attributes)
108109
*/
109110
enum nf_tables_msg_types {
110111
NFT_MSG_NEWTABLE,
@@ -140,6 +141,7 @@ enum nf_tables_msg_types {
140141
NFT_MSG_DESTROYSETELEM,
141142
NFT_MSG_DESTROYOBJ,
142143
NFT_MSG_DESTROYFLOWTABLE,
144+
NFT_MSG_GETSETELEM_RESET,
143145
NFT_MSG_MAX,
144146
};
145147

net/netfilter/nf_tables_api.c

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5229,7 +5229,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
52295229

52305230
static int nft_set_elem_expr_dump(struct sk_buff *skb,
52315231
const struct nft_set *set,
5232-
const struct nft_set_ext *ext)
5232+
const struct nft_set_ext *ext,
5233+
bool reset)
52335234
{
52345235
struct nft_set_elem_expr *elem_expr;
52355236
u32 size, num_exprs = 0;
@@ -5242,7 +5243,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
52425243

52435244
if (num_exprs == 1) {
52445245
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)
52465247
return -1;
52475248

52485249
return 0;
@@ -5253,7 +5254,7 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
52535254

52545255
nft_setelem_expr_foreach(expr, elem_expr, size) {
52555256
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)
52575258
goto nla_put_failure;
52585259
}
52595260
nla_nest_end(skb, nest);
@@ -5266,11 +5267,13 @@ static int nft_set_elem_expr_dump(struct sk_buff *skb,
52665267

52675268
static int nf_tables_fill_setelem(struct sk_buff *skb,
52685269
const struct nft_set *set,
5269-
const struct nft_set_elem *elem)
5270+
const struct nft_set_elem *elem,
5271+
bool reset)
52705272
{
52715273
const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
52725274
unsigned char *b = skb_tail_pointer(skb);
52735275
struct nlattr *nest;
5276+
u64 timeout = 0;
52745277

52755278
nest = nla_nest_start_noflag(skb, NFTA_LIST_ELEM);
52765279
if (nest == NULL)
@@ -5293,7 +5296,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
52935296
goto nla_put_failure;
52945297

52955298
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))
52975300
goto nla_put_failure;
52985301

52995302
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
@@ -5306,11 +5309,15 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
53065309
htonl(*nft_set_ext_flags(ext))))
53075310
goto nla_put_failure;
53085311

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+
}
53145321

53155322
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
53165323
u64 expires, now = get_jiffies_64();
@@ -5325,6 +5332,9 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
53255332
nf_jiffies64_to_msecs(expires),
53265333
NFTA_SET_ELEM_PAD))
53275334
goto nla_put_failure;
5335+
5336+
if (reset)
5337+
*nft_set_ext_expiration(ext) = now + timeout;
53285338
}
53295339

53305340
if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
@@ -5348,6 +5358,7 @@ struct nft_set_dump_args {
53485358
const struct netlink_callback *cb;
53495359
struct nft_set_iter iter;
53505360
struct sk_buff *skb;
5361+
bool reset;
53515362
};
53525363

53535364
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,
53585369
struct nft_set_dump_args *args;
53595370

53605371
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);
53625373
}
53635374

53645375
struct nft_set_dump_ctx {
@@ -5367,7 +5378,7 @@ struct nft_set_dump_ctx {
53675378
};
53685379

53695380
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)
53715382
{
53725383
struct nft_set_elem_catchall *catchall;
53735384
u8 genmask = nft_genmask_cur(net);
@@ -5382,7 +5393,7 @@ static int nft_set_catchall_dump(struct net *net, struct sk_buff *skb,
53825393
continue;
53835394

53845395
elem.priv = catchall->elem;
5385-
ret = nf_tables_fill_setelem(skb, set, &elem);
5396+
ret = nf_tables_fill_setelem(skb, set, &elem, reset);
53865397
break;
53875398
}
53885399

@@ -5400,6 +5411,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
54005411
bool set_found = false;
54015412
struct nlmsghdr *nlh;
54025413
struct nlattr *nest;
5414+
bool reset = false;
54035415
u32 portid, seq;
54045416
int event;
54055417

@@ -5447,8 +5459,12 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
54475459
if (nest == NULL)
54485460
goto nla_put_failure;
54495461

5462+
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
5463+
reset = true;
5464+
54505465
args.cb = cb;
54515466
args.skb = skb;
5467+
args.reset = reset;
54525468
args.iter.genmask = nft_genmask_cur(net);
54535469
args.iter.skip = cb->args[0];
54545470
args.iter.count = 0;
@@ -5457,7 +5473,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
54575473
set->ops->walk(&dump_ctx->ctx, set, &args.iter);
54585474

54595475
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);
54615477
rcu_read_unlock();
54625478

54635479
nla_nest_end(skb, nest);
@@ -5495,7 +5511,8 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
54955511
const struct nft_ctx *ctx, u32 seq,
54965512
u32 portid, int event, u16 flags,
54975513
const struct nft_set *set,
5498-
const struct nft_set_elem *elem)
5514+
const struct nft_set_elem *elem,
5515+
bool reset)
54995516
{
55005517
struct nlmsghdr *nlh;
55015518
struct nlattr *nest;
@@ -5516,7 +5533,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
55165533
if (nest == NULL)
55175534
goto nla_put_failure;
55185535

5519-
err = nf_tables_fill_setelem(skb, set, elem);
5536+
err = nf_tables_fill_setelem(skb, set, elem, reset);
55205537
if (err < 0)
55215538
goto nla_put_failure;
55225539

@@ -5622,7 +5639,7 @@ static int nft_setelem_get(struct nft_ctx *ctx, struct nft_set *set,
56225639
}
56235640

56245641
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)
56265643
{
56275644
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
56285645
struct nft_set_elem elem;
@@ -5666,7 +5683,8 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
56665683
return err;
56675684

56685685
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);
56705688
if (err < 0)
56715689
goto err_fill_setelem;
56725690

@@ -5690,6 +5708,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
56905708
struct nft_set *set;
56915709
struct nlattr *attr;
56925710
struct nft_ctx ctx;
5711+
bool reset = false;
56935712
int rem, err = 0;
56945713

56955714
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,
57245743
if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
57255744
return -EINVAL;
57265745

5746+
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
5747+
reset = true;
5748+
57275749
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);
57295751
if (err < 0) {
57305752
NL_SET_BAD_ATTR(extack, attr);
57315753
break;
@@ -5758,7 +5780,7 @@ static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
57585780
flags |= ctx->flags & (NLM_F_CREATE | NLM_F_EXCL);
57595781

57605782
err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
5761-
set, elem);
5783+
set, elem, false);
57625784
if (err < 0) {
57635785
kfree_skb(skb);
57645786
goto err;
@@ -8715,6 +8737,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
87158737
.attr_count = NFTA_SET_ELEM_LIST_MAX,
87168738
.policy = nft_set_elem_list_policy,
87178739
},
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+
},
87188746
[NFT_MSG_DELSETELEM] = {
87198747
.call = nf_tables_delsetelem,
87208748
.type = NFNL_CB_BATCH,

0 commit comments

Comments
 (0)