1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <linux/module.h>
5 #include <linux/netlink.h>
6 #include <linux/netfilter.h>
7 #include <linux/netfilter/nf_tables.h>
8 #include <net/netfilter/nf_tables_core.h>
9 #include <net/netfilter/nf_tables.h>
12 unsigned long jiffies
;
16 struct nft_last_priv
{
17 struct nft_last
*last
;
20 static const struct nla_policy nft_last_policy
[NFTA_LAST_MAX
+ 1] = {
21 [NFTA_LAST_SET
] = { .type
= NLA_U32
},
22 [NFTA_LAST_MSECS
] = { .type
= NLA_U64
},
25 static int nft_last_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
26 const struct nlattr
* const tb
[])
28 struct nft_last_priv
*priv
= nft_expr_priv(expr
);
29 struct nft_last
*last
;
33 last
= kzalloc(sizeof(*last
), GFP_KERNEL_ACCOUNT
);
37 if (tb
[NFTA_LAST_SET
])
38 last
->set
= ntohl(nla_get_be32(tb
[NFTA_LAST_SET
]));
40 if (last
->set
&& tb
[NFTA_LAST_MSECS
]) {
41 err
= nf_msecs_to_jiffies64(tb
[NFTA_LAST_MSECS
], &last_jiffies
);
45 last
->jiffies
= jiffies
- (unsigned long)last_jiffies
;
56 static void nft_last_eval(const struct nft_expr
*expr
,
57 struct nft_regs
*regs
, const struct nft_pktinfo
*pkt
)
59 struct nft_last_priv
*priv
= nft_expr_priv(expr
);
60 struct nft_last
*last
= priv
->last
;
62 if (READ_ONCE(last
->jiffies
) != jiffies
)
63 WRITE_ONCE(last
->jiffies
, jiffies
);
64 if (READ_ONCE(last
->set
) == 0)
65 WRITE_ONCE(last
->set
, 1);
68 static int nft_last_dump(struct sk_buff
*skb
,
69 const struct nft_expr
*expr
, bool reset
)
71 struct nft_last_priv
*priv
= nft_expr_priv(expr
);
72 struct nft_last
*last
= priv
->last
;
73 unsigned long last_jiffies
= READ_ONCE(last
->jiffies
);
74 u32 last_set
= READ_ONCE(last
->set
);
77 if (time_before(jiffies
, last_jiffies
)) {
78 WRITE_ONCE(last
->set
, 0);
83 msecs
= nf_jiffies64_to_msecs(jiffies
- last_jiffies
);
87 if (nla_put_be32(skb
, NFTA_LAST_SET
, htonl(last_set
)) ||
88 nla_put_be64(skb
, NFTA_LAST_MSECS
, msecs
, NFTA_LAST_PAD
))
97 static void nft_last_destroy(const struct nft_ctx
*ctx
,
98 const struct nft_expr
*expr
)
100 struct nft_last_priv
*priv
= nft_expr_priv(expr
);
105 static int nft_last_clone(struct nft_expr
*dst
, const struct nft_expr
*src
, gfp_t gfp
)
107 struct nft_last_priv
*priv_dst
= nft_expr_priv(dst
);
108 struct nft_last_priv
*priv_src
= nft_expr_priv(src
);
110 priv_dst
->last
= kzalloc(sizeof(*priv_dst
->last
), gfp
);
114 priv_dst
->last
->set
= priv_src
->last
->set
;
115 priv_dst
->last
->jiffies
= priv_src
->last
->jiffies
;
120 static const struct nft_expr_ops nft_last_ops
= {
121 .type
= &nft_last_type
,
122 .size
= NFT_EXPR_SIZE(sizeof(struct nft_last_priv
)),
123 .eval
= nft_last_eval
,
124 .init
= nft_last_init
,
125 .destroy
= nft_last_destroy
,
126 .clone
= nft_last_clone
,
127 .dump
= nft_last_dump
,
128 .reduce
= NFT_REDUCE_READONLY
,
131 struct nft_expr_type nft_last_type __read_mostly
= {
133 .ops
= &nft_last_ops
,
134 .policy
= nft_last_policy
,
135 .maxattr
= NFTA_LAST_MAX
,
136 .flags
= NFT_EXPR_STATEFUL
,
137 .owner
= THIS_MODULE
,