0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/netlink.h>
0013 #include <linux/netfilter.h>
0014 #include <linux/netfilter/nf_tables.h>
0015 #include <net/netfilter/nf_tables.h>
0016
0017 struct nft_limit {
0018 spinlock_t lock;
0019 u64 last;
0020 u64 tokens;
0021 };
0022
0023 struct nft_limit_priv {
0024 struct nft_limit *limit;
0025 u64 tokens_max;
0026 u64 rate;
0027 u64 nsecs;
0028 u32 burst;
0029 bool invert;
0030 };
0031
0032 static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)
0033 {
0034 u64 now, tokens;
0035 s64 delta;
0036
0037 spin_lock_bh(&priv->limit->lock);
0038 now = ktime_get_ns();
0039 tokens = priv->limit->tokens + now - priv->limit->last;
0040 if (tokens > priv->tokens_max)
0041 tokens = priv->tokens_max;
0042
0043 priv->limit->last = now;
0044 delta = tokens - cost;
0045 if (delta >= 0) {
0046 priv->limit->tokens = delta;
0047 spin_unlock_bh(&priv->limit->lock);
0048 return priv->invert;
0049 }
0050 priv->limit->tokens = tokens;
0051 spin_unlock_bh(&priv->limit->lock);
0052 return !priv->invert;
0053 }
0054
0055
0056 #define NFT_LIMIT_PKT_BURST_DEFAULT 5
0057
0058 static int nft_limit_init(struct nft_limit_priv *priv,
0059 const struct nlattr * const tb[], bool pkts)
0060 {
0061 u64 unit, tokens;
0062
0063 if (tb[NFTA_LIMIT_RATE] == NULL ||
0064 tb[NFTA_LIMIT_UNIT] == NULL)
0065 return -EINVAL;
0066
0067 priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE]));
0068 unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT]));
0069 priv->nsecs = unit * NSEC_PER_SEC;
0070 if (priv->rate == 0 || priv->nsecs < unit)
0071 return -EOVERFLOW;
0072
0073 if (tb[NFTA_LIMIT_BURST])
0074 priv->burst = ntohl(nla_get_be32(tb[NFTA_LIMIT_BURST]));
0075
0076 if (pkts && priv->burst == 0)
0077 priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT;
0078
0079 if (priv->rate + priv->burst < priv->rate)
0080 return -EOVERFLOW;
0081
0082 if (pkts) {
0083 tokens = div64_u64(priv->nsecs, priv->rate) * priv->burst;
0084 } else {
0085
0086
0087
0088
0089 tokens = div64_u64(priv->nsecs * (priv->rate + priv->burst),
0090 priv->rate);
0091 }
0092
0093 priv->limit = kmalloc(sizeof(*priv->limit), GFP_KERNEL_ACCOUNT);
0094 if (!priv->limit)
0095 return -ENOMEM;
0096
0097 priv->limit->tokens = tokens;
0098 priv->tokens_max = priv->limit->tokens;
0099
0100 if (tb[NFTA_LIMIT_FLAGS]) {
0101 u32 flags = ntohl(nla_get_be32(tb[NFTA_LIMIT_FLAGS]));
0102
0103 if (flags & NFT_LIMIT_F_INV)
0104 priv->invert = true;
0105 }
0106 priv->limit->last = ktime_get_ns();
0107 spin_lock_init(&priv->limit->lock);
0108
0109 return 0;
0110 }
0111
0112 static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit_priv *priv,
0113 enum nft_limit_type type)
0114 {
0115 u32 flags = priv->invert ? NFT_LIMIT_F_INV : 0;
0116 u64 secs = div_u64(priv->nsecs, NSEC_PER_SEC);
0117
0118 if (nla_put_be64(skb, NFTA_LIMIT_RATE, cpu_to_be64(priv->rate),
0119 NFTA_LIMIT_PAD) ||
0120 nla_put_be64(skb, NFTA_LIMIT_UNIT, cpu_to_be64(secs),
0121 NFTA_LIMIT_PAD) ||
0122 nla_put_be32(skb, NFTA_LIMIT_BURST, htonl(priv->burst)) ||
0123 nla_put_be32(skb, NFTA_LIMIT_TYPE, htonl(type)) ||
0124 nla_put_be32(skb, NFTA_LIMIT_FLAGS, htonl(flags)))
0125 goto nla_put_failure;
0126 return 0;
0127
0128 nla_put_failure:
0129 return -1;
0130 }
0131
0132 static void nft_limit_destroy(const struct nft_ctx *ctx,
0133 const struct nft_limit_priv *priv)
0134 {
0135 kfree(priv->limit);
0136 }
0137
0138 static int nft_limit_clone(struct nft_limit_priv *priv_dst,
0139 const struct nft_limit_priv *priv_src)
0140 {
0141 priv_dst->tokens_max = priv_src->tokens_max;
0142 priv_dst->rate = priv_src->rate;
0143 priv_dst->nsecs = priv_src->nsecs;
0144 priv_dst->burst = priv_src->burst;
0145 priv_dst->invert = priv_src->invert;
0146
0147 priv_dst->limit = kmalloc(sizeof(*priv_dst->limit), GFP_ATOMIC);
0148 if (!priv_dst->limit)
0149 return -ENOMEM;
0150
0151 spin_lock_init(&priv_dst->limit->lock);
0152 priv_dst->limit->tokens = priv_src->tokens_max;
0153 priv_dst->limit->last = ktime_get_ns();
0154
0155 return 0;
0156 }
0157
0158 struct nft_limit_priv_pkts {
0159 struct nft_limit_priv limit;
0160 u64 cost;
0161 };
0162
0163 static void nft_limit_pkts_eval(const struct nft_expr *expr,
0164 struct nft_regs *regs,
0165 const struct nft_pktinfo *pkt)
0166 {
0167 struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
0168
0169 if (nft_limit_eval(&priv->limit, priv->cost))
0170 regs->verdict.code = NFT_BREAK;
0171 }
0172
0173 static const struct nla_policy nft_limit_policy[NFTA_LIMIT_MAX + 1] = {
0174 [NFTA_LIMIT_RATE] = { .type = NLA_U64 },
0175 [NFTA_LIMIT_UNIT] = { .type = NLA_U64 },
0176 [NFTA_LIMIT_BURST] = { .type = NLA_U32 },
0177 [NFTA_LIMIT_TYPE] = { .type = NLA_U32 },
0178 [NFTA_LIMIT_FLAGS] = { .type = NLA_U32 },
0179 };
0180
0181 static int nft_limit_pkts_init(const struct nft_ctx *ctx,
0182 const struct nft_expr *expr,
0183 const struct nlattr * const tb[])
0184 {
0185 struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
0186 int err;
0187
0188 err = nft_limit_init(&priv->limit, tb, true);
0189 if (err < 0)
0190 return err;
0191
0192 priv->cost = div64_u64(priv->limit.nsecs, priv->limit.rate);
0193 return 0;
0194 }
0195
0196 static int nft_limit_pkts_dump(struct sk_buff *skb, const struct nft_expr *expr)
0197 {
0198 const struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
0199
0200 return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
0201 }
0202
0203 static void nft_limit_pkts_destroy(const struct nft_ctx *ctx,
0204 const struct nft_expr *expr)
0205 {
0206 const struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);
0207
0208 nft_limit_destroy(ctx, &priv->limit);
0209 }
0210
0211 static int nft_limit_pkts_clone(struct nft_expr *dst, const struct nft_expr *src)
0212 {
0213 struct nft_limit_priv_pkts *priv_dst = nft_expr_priv(dst);
0214 struct nft_limit_priv_pkts *priv_src = nft_expr_priv(src);
0215
0216 priv_dst->cost = priv_src->cost;
0217
0218 return nft_limit_clone(&priv_dst->limit, &priv_src->limit);
0219 }
0220
0221 static struct nft_expr_type nft_limit_type;
0222 static const struct nft_expr_ops nft_limit_pkts_ops = {
0223 .type = &nft_limit_type,
0224 .size = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)),
0225 .eval = nft_limit_pkts_eval,
0226 .init = nft_limit_pkts_init,
0227 .destroy = nft_limit_pkts_destroy,
0228 .clone = nft_limit_pkts_clone,
0229 .dump = nft_limit_pkts_dump,
0230 .reduce = NFT_REDUCE_READONLY,
0231 };
0232
0233 static void nft_limit_bytes_eval(const struct nft_expr *expr,
0234 struct nft_regs *regs,
0235 const struct nft_pktinfo *pkt)
0236 {
0237 struct nft_limit_priv *priv = nft_expr_priv(expr);
0238 u64 cost = div64_u64(priv->nsecs * pkt->skb->len, priv->rate);
0239
0240 if (nft_limit_eval(priv, cost))
0241 regs->verdict.code = NFT_BREAK;
0242 }
0243
0244 static int nft_limit_bytes_init(const struct nft_ctx *ctx,
0245 const struct nft_expr *expr,
0246 const struct nlattr * const tb[])
0247 {
0248 struct nft_limit_priv *priv = nft_expr_priv(expr);
0249
0250 return nft_limit_init(priv, tb, false);
0251 }
0252
0253 static int nft_limit_bytes_dump(struct sk_buff *skb,
0254 const struct nft_expr *expr)
0255 {
0256 const struct nft_limit_priv *priv = nft_expr_priv(expr);
0257
0258 return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
0259 }
0260
0261 static void nft_limit_bytes_destroy(const struct nft_ctx *ctx,
0262 const struct nft_expr *expr)
0263 {
0264 const struct nft_limit_priv *priv = nft_expr_priv(expr);
0265
0266 nft_limit_destroy(ctx, priv);
0267 }
0268
0269 static int nft_limit_bytes_clone(struct nft_expr *dst, const struct nft_expr *src)
0270 {
0271 struct nft_limit_priv *priv_dst = nft_expr_priv(dst);
0272 struct nft_limit_priv *priv_src = nft_expr_priv(src);
0273
0274 return nft_limit_clone(priv_dst, priv_src);
0275 }
0276
0277 static const struct nft_expr_ops nft_limit_bytes_ops = {
0278 .type = &nft_limit_type,
0279 .size = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv)),
0280 .eval = nft_limit_bytes_eval,
0281 .init = nft_limit_bytes_init,
0282 .dump = nft_limit_bytes_dump,
0283 .clone = nft_limit_bytes_clone,
0284 .destroy = nft_limit_bytes_destroy,
0285 .reduce = NFT_REDUCE_READONLY,
0286 };
0287
0288 static const struct nft_expr_ops *
0289 nft_limit_select_ops(const struct nft_ctx *ctx,
0290 const struct nlattr * const tb[])
0291 {
0292 if (tb[NFTA_LIMIT_TYPE] == NULL)
0293 return &nft_limit_pkts_ops;
0294
0295 switch (ntohl(nla_get_be32(tb[NFTA_LIMIT_TYPE]))) {
0296 case NFT_LIMIT_PKTS:
0297 return &nft_limit_pkts_ops;
0298 case NFT_LIMIT_PKT_BYTES:
0299 return &nft_limit_bytes_ops;
0300 }
0301 return ERR_PTR(-EOPNOTSUPP);
0302 }
0303
0304 static struct nft_expr_type nft_limit_type __read_mostly = {
0305 .name = "limit",
0306 .select_ops = nft_limit_select_ops,
0307 .policy = nft_limit_policy,
0308 .maxattr = NFTA_LIMIT_MAX,
0309 .flags = NFT_EXPR_STATEFUL,
0310 .owner = THIS_MODULE,
0311 };
0312
0313 static void nft_limit_obj_pkts_eval(struct nft_object *obj,
0314 struct nft_regs *regs,
0315 const struct nft_pktinfo *pkt)
0316 {
0317 struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
0318
0319 if (nft_limit_eval(&priv->limit, priv->cost))
0320 regs->verdict.code = NFT_BREAK;
0321 }
0322
0323 static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,
0324 const struct nlattr * const tb[],
0325 struct nft_object *obj)
0326 {
0327 struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
0328 int err;
0329
0330 err = nft_limit_init(&priv->limit, tb, true);
0331 if (err < 0)
0332 return err;
0333
0334 priv->cost = div64_u64(priv->limit.nsecs, priv->limit.rate);
0335 return 0;
0336 }
0337
0338 static int nft_limit_obj_pkts_dump(struct sk_buff *skb,
0339 struct nft_object *obj,
0340 bool reset)
0341 {
0342 const struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
0343
0344 return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
0345 }
0346
0347 static void nft_limit_obj_pkts_destroy(const struct nft_ctx *ctx,
0348 struct nft_object *obj)
0349 {
0350 struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
0351
0352 nft_limit_destroy(ctx, &priv->limit);
0353 }
0354
0355 static struct nft_object_type nft_limit_obj_type;
0356 static const struct nft_object_ops nft_limit_obj_pkts_ops = {
0357 .type = &nft_limit_obj_type,
0358 .size = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)),
0359 .init = nft_limit_obj_pkts_init,
0360 .destroy = nft_limit_obj_pkts_destroy,
0361 .eval = nft_limit_obj_pkts_eval,
0362 .dump = nft_limit_obj_pkts_dump,
0363 };
0364
0365 static void nft_limit_obj_bytes_eval(struct nft_object *obj,
0366 struct nft_regs *regs,
0367 const struct nft_pktinfo *pkt)
0368 {
0369 struct nft_limit_priv *priv = nft_obj_data(obj);
0370 u64 cost = div64_u64(priv->nsecs * pkt->skb->len, priv->rate);
0371
0372 if (nft_limit_eval(priv, cost))
0373 regs->verdict.code = NFT_BREAK;
0374 }
0375
0376 static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,
0377 const struct nlattr * const tb[],
0378 struct nft_object *obj)
0379 {
0380 struct nft_limit_priv *priv = nft_obj_data(obj);
0381
0382 return nft_limit_init(priv, tb, false);
0383 }
0384
0385 static int nft_limit_obj_bytes_dump(struct sk_buff *skb,
0386 struct nft_object *obj,
0387 bool reset)
0388 {
0389 const struct nft_limit_priv *priv = nft_obj_data(obj);
0390
0391 return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
0392 }
0393
0394 static void nft_limit_obj_bytes_destroy(const struct nft_ctx *ctx,
0395 struct nft_object *obj)
0396 {
0397 struct nft_limit_priv *priv = nft_obj_data(obj);
0398
0399 nft_limit_destroy(ctx, priv);
0400 }
0401
0402 static struct nft_object_type nft_limit_obj_type;
0403 static const struct nft_object_ops nft_limit_obj_bytes_ops = {
0404 .type = &nft_limit_obj_type,
0405 .size = sizeof(struct nft_limit_priv),
0406 .init = nft_limit_obj_bytes_init,
0407 .destroy = nft_limit_obj_bytes_destroy,
0408 .eval = nft_limit_obj_bytes_eval,
0409 .dump = nft_limit_obj_bytes_dump,
0410 };
0411
0412 static const struct nft_object_ops *
0413 nft_limit_obj_select_ops(const struct nft_ctx *ctx,
0414 const struct nlattr * const tb[])
0415 {
0416 if (!tb[NFTA_LIMIT_TYPE])
0417 return &nft_limit_obj_pkts_ops;
0418
0419 switch (ntohl(nla_get_be32(tb[NFTA_LIMIT_TYPE]))) {
0420 case NFT_LIMIT_PKTS:
0421 return &nft_limit_obj_pkts_ops;
0422 case NFT_LIMIT_PKT_BYTES:
0423 return &nft_limit_obj_bytes_ops;
0424 }
0425 return ERR_PTR(-EOPNOTSUPP);
0426 }
0427
0428 static struct nft_object_type nft_limit_obj_type __read_mostly = {
0429 .select_ops = nft_limit_obj_select_ops,
0430 .type = NFT_OBJECT_LIMIT,
0431 .maxattr = NFTA_LIMIT_MAX,
0432 .policy = nft_limit_policy,
0433 .owner = THIS_MODULE,
0434 };
0435
0436 static int __init nft_limit_module_init(void)
0437 {
0438 int err;
0439
0440 err = nft_register_obj(&nft_limit_obj_type);
0441 if (err < 0)
0442 return err;
0443
0444 err = nft_register_expr(&nft_limit_type);
0445 if (err < 0)
0446 goto err1;
0447
0448 return 0;
0449 err1:
0450 nft_unregister_obj(&nft_limit_obj_type);
0451 return err;
0452 }
0453
0454 static void __exit nft_limit_module_exit(void)
0455 {
0456 nft_unregister_expr(&nft_limit_type);
0457 nft_unregister_obj(&nft_limit_obj_type);
0458 }
0459
0460 module_init(nft_limit_module_init);
0461 module_exit(nft_limit_module_exit);
0462
0463 MODULE_LICENSE("GPL");
0464 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
0465 MODULE_ALIAS_NFT_EXPR("limit");
0466 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_LIMIT);
0467 MODULE_DESCRIPTION("nftables limit expression support");