|
@@ -229,14 +229,133 @@ static struct nft_expr_type nft_limit_type __read_mostly = {
|
|
|
.owner = THIS_MODULE,
|
|
|
};
|
|
|
|
|
|
+static void nft_limit_obj_pkts_eval(struct nft_object *obj,
|
|
|
+ struct nft_regs *regs,
|
|
|
+ const struct nft_pktinfo *pkt)
|
|
|
+{
|
|
|
+ struct nft_limit_pkts *priv = nft_obj_data(obj);
|
|
|
+
|
|
|
+ if (nft_limit_eval(&priv->limit, priv->cost))
|
|
|
+ regs->verdict.code = NFT_BREAK;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,
|
|
|
+ const struct nlattr * const tb[],
|
|
|
+ struct nft_object *obj)
|
|
|
+{
|
|
|
+ struct nft_limit_pkts *priv = nft_obj_data(obj);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nft_limit_init(&priv->limit, tb);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ priv->cost = div64_u64(priv->limit.nsecs, priv->limit.rate);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_limit_obj_pkts_dump(struct sk_buff *skb,
|
|
|
+ struct nft_object *obj,
|
|
|
+ bool reset)
|
|
|
+{
|
|
|
+ const struct nft_limit_pkts *priv = nft_obj_data(obj);
|
|
|
+
|
|
|
+ return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
|
|
|
+}
|
|
|
+
|
|
|
+static struct nft_object_type nft_limit_obj_type;
|
|
|
+static const struct nft_object_ops nft_limit_obj_pkts_ops = {
|
|
|
+ .type = &nft_limit_obj_type,
|
|
|
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_limit_pkts)),
|
|
|
+ .init = nft_limit_obj_pkts_init,
|
|
|
+ .eval = nft_limit_obj_pkts_eval,
|
|
|
+ .dump = nft_limit_obj_pkts_dump,
|
|
|
+};
|
|
|
+
|
|
|
+static void nft_limit_obj_bytes_eval(struct nft_object *obj,
|
|
|
+ struct nft_regs *regs,
|
|
|
+ const struct nft_pktinfo *pkt)
|
|
|
+{
|
|
|
+ struct nft_limit *priv = nft_obj_data(obj);
|
|
|
+ u64 cost = div64_u64(priv->nsecs * pkt->skb->len, priv->rate);
|
|
|
+
|
|
|
+ if (nft_limit_eval(priv, cost))
|
|
|
+ regs->verdict.code = NFT_BREAK;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,
|
|
|
+ const struct nlattr * const tb[],
|
|
|
+ struct nft_object *obj)
|
|
|
+{
|
|
|
+ struct nft_limit *priv = nft_obj_data(obj);
|
|
|
+
|
|
|
+ return nft_limit_init(priv, tb);
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_limit_obj_bytes_dump(struct sk_buff *skb,
|
|
|
+ struct nft_object *obj,
|
|
|
+ bool reset)
|
|
|
+{
|
|
|
+ const struct nft_limit *priv = nft_obj_data(obj);
|
|
|
+
|
|
|
+ return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
|
|
|
+}
|
|
|
+
|
|
|
+static struct nft_object_type nft_limit_obj_type;
|
|
|
+static const struct nft_object_ops nft_limit_obj_bytes_ops = {
|
|
|
+ .type = &nft_limit_obj_type,
|
|
|
+ .size = sizeof(struct nft_limit),
|
|
|
+ .init = nft_limit_obj_bytes_init,
|
|
|
+ .eval = nft_limit_obj_bytes_eval,
|
|
|
+ .dump = nft_limit_obj_bytes_dump,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct nft_object_ops *
|
|
|
+nft_limit_obj_select_ops(const struct nft_ctx *ctx,
|
|
|
+ const struct nlattr * const tb[])
|
|
|
+{
|
|
|
+ if (!tb[NFTA_LIMIT_TYPE])
|
|
|
+ return &nft_limit_obj_pkts_ops;
|
|
|
+
|
|
|
+ switch (ntohl(nla_get_be32(tb[NFTA_LIMIT_TYPE]))) {
|
|
|
+ case NFT_LIMIT_PKTS:
|
|
|
+ return &nft_limit_obj_pkts_ops;
|
|
|
+ case NFT_LIMIT_PKT_BYTES:
|
|
|
+ return &nft_limit_obj_bytes_ops;
|
|
|
+ }
|
|
|
+ return ERR_PTR(-EOPNOTSUPP);
|
|
|
+}
|
|
|
+
|
|
|
+static struct nft_object_type nft_limit_obj_type __read_mostly = {
|
|
|
+ .select_ops = nft_limit_obj_select_ops,
|
|
|
+ .type = NFT_OBJECT_LIMIT,
|
|
|
+ .maxattr = NFTA_LIMIT_MAX,
|
|
|
+ .policy = nft_limit_policy,
|
|
|
+ .owner = THIS_MODULE,
|
|
|
+};
|
|
|
+
|
|
|
static int __init nft_limit_module_init(void)
|
|
|
{
|
|
|
- return nft_register_expr(&nft_limit_type);
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nft_register_obj(&nft_limit_obj_type);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = nft_register_expr(&nft_limit_type);
|
|
|
+ if (err < 0)
|
|
|
+ goto err1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+err1:
|
|
|
+ nft_unregister_obj(&nft_limit_obj_type);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static void __exit nft_limit_module_exit(void)
|
|
|
{
|
|
|
nft_unregister_expr(&nft_limit_type);
|
|
|
+ nft_unregister_obj(&nft_limit_obj_type);
|
|
|
}
|
|
|
|
|
|
module_init(nft_limit_module_init);
|
|
@@ -245,3 +364,4 @@ module_exit(nft_limit_module_exit);
|
|
|
MODULE_LICENSE("GPL");
|
|
|
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
|
|
MODULE_ALIAS_NFT_EXPR("limit");
|
|
|
+MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_LIMIT);
|