diff options
-rw-r--r-- | include/net/netfilter/nf_tables.h | 13 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 56 |
2 files changed, 64 insertions, 5 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index cb42da1011ef..e21623cb7b20 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _NET_NF_TABLES_H | 1 | #ifndef _NET_NF_TABLES_H |
2 | #define _NET_NF_TABLES_H | 2 | #define _NET_NF_TABLES_H |
3 | 3 | ||
4 | #include <linux/module.h> | ||
4 | #include <linux/list.h> | 5 | #include <linux/list.h> |
5 | #include <linux/netfilter.h> | 6 | #include <linux/netfilter.h> |
6 | #include <linux/netfilter/nfnetlink.h> | 7 | #include <linux/netfilter/nfnetlink.h> |
@@ -641,6 +642,18 @@ static inline void *nft_expr_priv(const struct nft_expr *expr) | |||
641 | return (void *)expr->data; | 642 | return (void *)expr->data; |
642 | } | 643 | } |
643 | 644 | ||
645 | struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, | ||
646 | const struct nlattr *nla); | ||
647 | void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr); | ||
648 | int nft_expr_dump(struct sk_buff *skb, unsigned int attr, | ||
649 | const struct nft_expr *expr); | ||
650 | |||
651 | static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src) | ||
652 | { | ||
653 | __module_get(src->ops->type->owner); | ||
654 | memcpy(dst, src, src->ops->size); | ||
655 | } | ||
656 | |||
644 | /** | 657 | /** |
645 | * struct nft_rule - nf_tables rule | 658 | * struct nft_rule - nf_tables rule |
646 | * | 659 | * |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ed0e70ea2bc5..e97bee59fe08 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -1545,6 +1545,23 @@ nla_put_failure: | |||
1545 | return -1; | 1545 | return -1; |
1546 | }; | 1546 | }; |
1547 | 1547 | ||
1548 | int nft_expr_dump(struct sk_buff *skb, unsigned int attr, | ||
1549 | const struct nft_expr *expr) | ||
1550 | { | ||
1551 | struct nlattr *nest; | ||
1552 | |||
1553 | nest = nla_nest_start(skb, attr); | ||
1554 | if (!nest) | ||
1555 | goto nla_put_failure; | ||
1556 | if (nf_tables_fill_expr_info(skb, expr) < 0) | ||
1557 | goto nla_put_failure; | ||
1558 | nla_nest_end(skb, nest); | ||
1559 | return 0; | ||
1560 | |||
1561 | nla_put_failure: | ||
1562 | return -1; | ||
1563 | } | ||
1564 | |||
1548 | struct nft_expr_info { | 1565 | struct nft_expr_info { |
1549 | const struct nft_expr_ops *ops; | 1566 | const struct nft_expr_ops *ops; |
1550 | struct nlattr *tb[NFT_EXPR_MAXATTR + 1]; | 1567 | struct nlattr *tb[NFT_EXPR_MAXATTR + 1]; |
@@ -1622,6 +1639,39 @@ static void nf_tables_expr_destroy(const struct nft_ctx *ctx, | |||
1622 | module_put(expr->ops->type->owner); | 1639 | module_put(expr->ops->type->owner); |
1623 | } | 1640 | } |
1624 | 1641 | ||
1642 | struct nft_expr *nft_expr_init(const struct nft_ctx *ctx, | ||
1643 | const struct nlattr *nla) | ||
1644 | { | ||
1645 | struct nft_expr_info info; | ||
1646 | struct nft_expr *expr; | ||
1647 | int err; | ||
1648 | |||
1649 | err = nf_tables_expr_parse(ctx, nla, &info); | ||
1650 | if (err < 0) | ||
1651 | goto err1; | ||
1652 | |||
1653 | err = -ENOMEM; | ||
1654 | expr = kzalloc(info.ops->size, GFP_KERNEL); | ||
1655 | if (expr == NULL) | ||
1656 | goto err2; | ||
1657 | |||
1658 | err = nf_tables_newexpr(ctx, &info, expr); | ||
1659 | if (err < 0) | ||
1660 | goto err2; | ||
1661 | |||
1662 | return expr; | ||
1663 | err2: | ||
1664 | module_put(info.ops->type->owner); | ||
1665 | err1: | ||
1666 | return ERR_PTR(err); | ||
1667 | } | ||
1668 | |||
1669 | void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr) | ||
1670 | { | ||
1671 | nf_tables_expr_destroy(ctx, expr); | ||
1672 | kfree(expr); | ||
1673 | } | ||
1674 | |||
1625 | /* | 1675 | /* |
1626 | * Rules | 1676 | * Rules |
1627 | */ | 1677 | */ |
@@ -1703,12 +1753,8 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net, | |||
1703 | if (list == NULL) | 1753 | if (list == NULL) |
1704 | goto nla_put_failure; | 1754 | goto nla_put_failure; |
1705 | nft_rule_for_each_expr(expr, next, rule) { | 1755 | nft_rule_for_each_expr(expr, next, rule) { |
1706 | struct nlattr *elem = nla_nest_start(skb, NFTA_LIST_ELEM); | 1756 | if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0) |
1707 | if (elem == NULL) | ||
1708 | goto nla_put_failure; | ||
1709 | if (nf_tables_fill_expr_info(skb, expr) < 0) | ||
1710 | goto nla_put_failure; | 1757 | goto nla_put_failure; |
1711 | nla_nest_end(skb, elem); | ||
1712 | } | 1758 | } |
1713 | nla_nest_end(skb, list); | 1759 | nla_nest_end(skb, list); |
1714 | 1760 | ||