Mention branches and keyring.
[releases.git] / netfilter / nft_limit.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4  *
5  * Development of this code funded by Astaro AG (http://www.astaro.com/)
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/spinlock.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <net/netfilter/nf_tables.h>
16
17 struct nft_limit {
18         spinlock_t      lock;
19         u64             last;
20         u64             tokens;
21 };
22
23 struct nft_limit_priv {
24         struct nft_limit *limit;
25         u64             tokens_max;
26         u64             rate;
27         u64             nsecs;
28         u32             burst;
29         bool            invert;
30 };
31
32 static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
33 {
34         u64 now, tokens;
35         s64 delta;
36
37         spin_lock_bh(&priv->limit->lock);
38         now = ktime_get_ns();
39         tokens = priv->limit->tokens + now - priv->limit->last;
40         if (tokens > priv->tokens_max)
41                 tokens = priv->tokens_max;
42
43         priv->limit->last = now;
44         delta = tokens - cost;
45         if (delta >= 0) {
46                 priv->limit->tokens = delta;
47                 spin_unlock_bh(&priv->limit->lock);
48                 return priv->invert;
49         }
50         priv->limit->tokens = tokens;
51         spin_unlock_bh(&priv->limit->lock);
52         return !priv->invert;
53 }
54
55 /* Use same default as in iptables. */
56 #define NFT_LIMIT_PKT_BURST_DEFAULT     5
57
58 static int nft_limit_init(struct nft_limit_priv *priv,
59                           const struct nlattr * const tb[], bool pkts)
60 {
61         u64 unit, tokens, rate_with_burst;
62         bool invert = false;
63
64         if (tb[NFTA_LIMIT_RATE] == NULL ||
65             tb[NFTA_LIMIT_UNIT] == NULL)
66                 return -EINVAL;
67
68         priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
69         if (priv->rate == 0)
70                 return -EINVAL;
71
72         unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
73         if (check_mul_overflow(unit, NSEC_PER_SEC, &priv->nsecs))
74                 return -EOVERFLOW;
75
76         if (tb[NFTA_LIMIT_BURST])
77                 priv->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));
78
79         if (pkts && priv->burst == 0)
80                 priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
81
82         if (check_add_overflow(priv->rate, priv->burst, &rate_with_burst))
83                 return -EOVERFLOW;
84
85         if (pkts) {
86                 u64 tmp = div64_u64(priv->nsecs, priv->rate);
87
88                 if (check_mul_overflow(tmp, priv->burst, &tokens))
89                         return -EOVERFLOW;
90         } else {
91                 u64 tmp;
92
93                 /* The token bucket size limits the number of tokens can be
94                  * accumulated. tokens_max specifies the bucket size.
95                  * tokens_max = unit * (rate + burst) / rate.
96                  */
97                 if (check_mul_overflow(priv->nsecs, rate_with_burst, &tmp))
98                         return -EOVERFLOW;
99
100                 tokens = div64_u64(tmp, priv->rate);
101         }
102
103         if (tb[NFTA_LIMIT_FLAGS]) {
104                 u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
105
106                 if (flags & ~NFT_LIMIT_F_INV)
107                         return -EOPNOTSUPP;
108
109                 if (flags & NFT_LIMIT_F_INV)
110                         invert = true;
111         }
112
113         priv->limit = kmalloc(sizeof(*priv->limit), GFP_KERNEL_ACCOUNT);
114         if (!priv->limit)
115                 return -ENOMEM;
116
117         priv->limit->tokens = tokens;
118         priv->tokens_max = priv->limit->tokens;
119         priv->invert = invert;
120         priv->limit->last = ktime_get_ns();
121         spin_lock_init(&priv->limit->lock);
122
123         return 0;
124 }
125
126 static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit_priv *priv,
127                           enum nft_limit_type type)
128 {
129         u32 flags = priv->invert ? NFT_LIMIT_F_INV : 0;
130         u64 secs = div_u64(priv->nsecs, NSEC_PER_SEC);
131
132         if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(priv->rate),
133                          NFTA_LIMIT_PAD) ||
134             nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs),
135                          NFTA_LIMIT_PAD) ||
136             nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(priv->burst)) ||
137             nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) ||
138             nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags)))
139                 goto nla_put_failure;
140         return 0;
141
142 nla_put_failure:
143         return -1;
144 }
145
146 static void nft_limit_destroy(const struct nft_ctx *ctx,
147                               const struct nft_limit_priv *priv)
148 {
149         kfree(priv->limit);
150 }
151
152 static int nft_limit_clone(struct nft_limit_priv *priv_dst,
153                            const struct nft_limit_priv *priv_src)
154 {
155         priv_dst->tokens_max = priv_src->tokens_max;
156         priv_dst->rate = priv_src->rate;
157         priv_dst->nsecs = priv_src->nsecs;
158         priv_dst->burst = priv_src->burst;
159         priv_dst->invert = priv_src->invert;
160
161         priv_dst->limit = kmalloc(sizeof(*priv_dst->limit), GFP_ATOMIC);
162         if (!priv_dst->limit)
163                 return -ENOMEM;
164
165         spin_lock_init(&priv_dst->limit->lock);
166         priv_dst->limit->tokens = priv_src->tokens_max;
167         priv_dst->limit->last = ktime_get_ns();
168
169         return 0;
170 }
171
172 struct nft_limit_priv_pkts {
173         struct nft_limit_priv   limit;
174         u64                     cost;
175 };
176
177 static void nft_limit_pkts_eval(const struct nft_expr *expr,
178                                 struct nft_regs *regs,
179                                 const struct nft_pktinfo *pkt)
180 {
181         struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
182
183         if (nft_limit_eval(&priv->limit, priv->cost))
184                 regs->verdict.code = NFT_BREAK;
185 }
186
187 static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
188         [NFTA_LIMIT_RATE]       = { .type = NLA_U64 },
189         [NFTA_LIMIT_UNIT]       = { .type = NLA_U64 },
190         [NFTA_LIMIT_BURST]      = { .type = NLA_U32 },
191         [NFTA_LIMIT_TYPE]       = { .type = NLA_U32 },
192         [NFTA_LIMIT_FLAGS]      = { .type = NLA_U32 },
193 };
194
195 static int nft_limit_pkts_init(const struct nft_ctx *ctx,
196                                const struct nft_expr *expr,
197                                const struct nlattr * const tb[])
198 {
199         struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
200         int err;
201
202         err = nft_limit_init(&priv->limit, tb, true);
203         if (err < 0)
204                 return err;
205
206         priv->cost = div64_u64(priv->limit.nsecs, priv->limit.rate);
207         return 0;
208 }
209
210 static int nft_limit_pkts_dump(struct sk_buff *skb,
211                                const struct nft_expr *expr, bool reset)
212 {
213         const struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
214
215         return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
216 }
217
218 static void nft_limit_pkts_destroy(const struct nft_ctx *ctx,
219                                    const struct nft_expr *expr)
220 {
221         const struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
222
223         nft_limit_destroy(ctx, &priv->limit);
224 }
225
226 static int nft_limit_pkts_clone(struct nft_expr *dst, const struct nft_expr *src)
227 {
228         struct nft_limit_priv_pkts *priv_dst = nft_expr_priv(dst);
229         struct nft_limit_priv_pkts *priv_src = nft_expr_priv(src);
230
231         priv_dst->cost = priv_src->cost;
232
233         return nft_limit_clone(&priv_dst->limit, &priv_src->limit);
234 }
235
236 static struct nft_expr_type nft_limit_type;
237 static const struct nft_expr_ops nft_limit_pkts_ops = {
238         .type           = &nft_limit_type,
239         .size           = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)),
240         .eval           = nft_limit_pkts_eval,
241         .init           = nft_limit_pkts_init,
242         .destroy        = nft_limit_pkts_destroy,
243         .clone          = nft_limit_pkts_clone,
244         .dump           = nft_limit_pkts_dump,
245         .reduce         = NFT_REDUCE_READONLY,
246 };
247
248 static void nft_limit_bytes_eval(const struct nft_expr *expr,
249                                  struct nft_regs *regs,
250                                  const struct nft_pktinfo *pkt)
251 {
252         struct nft_limit_priv *priv = nft_expr_priv(expr);
253         u64 cost = div64_u64(priv->nsecs * pkt->skb->len, priv->rate);
254
255         if (nft_limit_eval(priv, cost))
256                 regs->verdict.code = NFT_BREAK;
257 }
258
259 static int nft_limit_bytes_init(const struct nft_ctx *ctx,
260                                 const struct nft_expr *expr,
261                                 const struct nlattr * const tb[])
262 {
263         struct nft_limit_priv *priv = nft_expr_priv(expr);
264
265         return nft_limit_init(priv, tb, false);
266 }
267
268 static int nft_limit_bytes_dump(struct sk_buff *skb,
269                                 const struct nft_expr *expr, bool reset)
270 {
271         const struct nft_limit_priv *priv = nft_expr_priv(expr);
272
273         return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
274 }
275
276 static void nft_limit_bytes_destroy(const struct nft_ctx *ctx,
277                                     const struct nft_expr *expr)
278 {
279         const struct nft_limit_priv *priv = nft_expr_priv(expr);
280
281         nft_limit_destroy(ctx, priv);
282 }
283
284 static int nft_limit_bytes_clone(struct nft_expr *dst, const struct nft_expr *src)
285 {
286         struct nft_limit_priv *priv_dst = nft_expr_priv(dst);
287         struct nft_limit_priv *priv_src = nft_expr_priv(src);
288
289         return nft_limit_clone(priv_dst, priv_src);
290 }
291
292 static const struct nft_expr_ops nft_limit_bytes_ops = {
293         .type           = &nft_limit_type,
294         .size           = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv)),
295         .eval           = nft_limit_bytes_eval,
296         .init           = nft_limit_bytes_init,
297         .dump           = nft_limit_bytes_dump,
298         .clone          = nft_limit_bytes_clone,
299         .destroy        = nft_limit_bytes_destroy,
300         .reduce         = NFT_REDUCE_READONLY,
301 };
302
303 static const struct nft_expr_ops *
304 nft_limit_select_ops(const struct nft_ctx *ctx,
305                      const struct nlattr * const tb[])
306 {
307         if (tb[NFTA_LIMIT_TYPE] == NULL)
308                 return &nft_limit_pkts_ops;
309
310         switch (ntohl(nla_get_be32(tb[NFTA_LIMIT_TYPE]))) {
311         case NFT_LIMIT_PKTS:
312                 return &nft_limit_pkts_ops;
313         case NFT_LIMIT_PKT_BYTES:
314                 return &nft_limit_bytes_ops;
315         }
316         return ERR_PTR(-EOPNOTSUPP);
317 }
318
319 static struct nft_expr_type nft_limit_type __read_mostly = {
320         .name           = "limit",
321         .select_ops     = nft_limit_select_ops,
322         .policy         = nft_limit_policy,
323         .maxattr        = NFTA_LIMIT_MAX,
324         .flags          = NFT_EXPR_STATEFUL,
325         .owner          = THIS_MODULE,
326 };
327
328 static void nft_limit_obj_pkts_eval(struct nft_object *obj,
329                                     struct nft_regs *regs,
330                                     const struct nft_pktinfo *pkt)
331 {
332         struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
333
334         if (nft_limit_eval(&priv->limit, priv->cost))
335                 regs->verdict.code = NFT_BREAK;
336 }
337
338 static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,
339                                    const struct nlattr * const tb[],
340                                    struct nft_object *obj)
341 {
342         struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
343         int err;
344
345         err = nft_limit_init(&priv->limit, tb, true);
346         if (err < 0)
347                 return err;
348
349         priv->cost = div64_u64(priv->limit.nsecs, priv->limit.rate);
350         return 0;
351 }
352
353 static int nft_limit_obj_pkts_dump(struct sk_buff *skb,
354                                    struct nft_object *obj,
355                                    bool reset)
356 {
357         const struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
358
359         return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
360 }
361
362 static void nft_limit_obj_pkts_destroy(const struct nft_ctx *ctx,
363                                        struct nft_object *obj)
364 {
365         struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
366
367         nft_limit_destroy(ctx, &priv->limit);
368 }
369
370 static struct nft_object_type nft_limit_obj_type;
371 static const struct nft_object_ops nft_limit_obj_pkts_ops = {
372         .type           = &nft_limit_obj_type,
373         .size           = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)),
374         .init           = nft_limit_obj_pkts_init,
375         .destroy        = nft_limit_obj_pkts_destroy,
376         .eval           = nft_limit_obj_pkts_eval,
377         .dump           = nft_limit_obj_pkts_dump,
378 };
379
380 static void nft_limit_obj_bytes_eval(struct nft_object *obj,
381                                      struct nft_regs *regs,
382                                      const struct nft_pktinfo *pkt)
383 {
384         struct nft_limit_priv *priv = nft_obj_data(obj);
385         u64 cost = div64_u64(priv->nsecs * pkt->skb->len, priv->rate);
386
387         if (nft_limit_eval(priv, cost))
388                 regs->verdict.code = NFT_BREAK;
389 }
390
391 static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,
392                                     const struct nlattr * const tb[],
393                                     struct nft_object *obj)
394 {
395         struct nft_limit_priv *priv = nft_obj_data(obj);
396
397         return nft_limit_init(priv, tb, false);
398 }
399
400 static int nft_limit_obj_bytes_dump(struct sk_buff *skb,
401                                     struct nft_object *obj,
402                                     bool reset)
403 {
404         const struct nft_limit_priv *priv = nft_obj_data(obj);
405
406         return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
407 }
408
409 static void nft_limit_obj_bytes_destroy(const struct nft_ctx *ctx,
410                                         struct nft_object *obj)
411 {
412         struct nft_limit_priv *priv = nft_obj_data(obj);
413
414         nft_limit_destroy(ctx, priv);
415 }
416
417 static struct nft_object_type nft_limit_obj_type;
418 static const struct nft_object_ops nft_limit_obj_bytes_ops = {
419         .type           = &nft_limit_obj_type,
420         .size           = sizeof(struct nft_limit_priv),
421         .init           = nft_limit_obj_bytes_init,
422         .destroy        = nft_limit_obj_bytes_destroy,
423         .eval           = nft_limit_obj_bytes_eval,
424         .dump           = nft_limit_obj_bytes_dump,
425 };
426
427 static const struct nft_object_ops *
428 nft_limit_obj_select_ops(const struct nft_ctx *ctx,
429                          const struct nlattr * const tb[])
430 {
431         if (!tb[NFTA_LIMIT_TYPE])
432                 return &nft_limit_obj_pkts_ops;
433
434         switch (ntohl(nla_get_be32(tb[NFTA_LIMIT_TYPE]))) {
435         case NFT_LIMIT_PKTS:
436                 return &nft_limit_obj_pkts_ops;
437         case NFT_LIMIT_PKT_BYTES:
438                 return &nft_limit_obj_bytes_ops;
439         }
440         return ERR_PTR(-EOPNOTSUPP);
441 }
442
443 static struct nft_object_type nft_limit_obj_type __read_mostly = {
444         .select_ops     = nft_limit_obj_select_ops,
445         .type           = NFT_OBJECT_LIMIT,
446         .maxattr        = NFTA_LIMIT_MAX,
447         .policy         = nft_limit_policy,
448         .owner          = THIS_MODULE,
449 };
450
451 static int __init nft_limit_module_init(void)
452 {
453         int err;
454
455         err = nft_register_obj(&nft_limit_obj_type);
456         if (err < 0)
457                 return err;
458
459         err = nft_register_expr(&nft_limit_type);
460         if (err < 0)
461                 goto err1;
462
463         return 0;
464 err1:
465         nft_unregister_obj(&nft_limit_obj_type);
466         return err;
467 }
468
469 static void __exit nft_limit_module_exit(void)
470 {
471         nft_unregister_expr(&nft_limit_type);
472         nft_unregister_obj(&nft_limit_obj_type);
473 }
474
475 module_init(nft_limit_module_init);
476 module_exit(nft_limit_module_exit);
477
478 MODULE_LICENSE("GPL");
479 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
480 MODULE_ALIAS_NFT_EXPR("limit");
481 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_LIMIT);
482 MODULE_DESCRIPTION("nftables limit expression support");