netfilter: nf_tables: add helper functions for expression handling

Add helper functions for initializing, cloning, dumping and destroying
a single expression that is not part of a rule.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Patrick McHardy 2015-04-11 10:46:38 +01:00 committed by Pablo Neira Ayuso
parent 24477e5741
commit 0b2d8a7b63
2 changed files with 64 additions and 5 deletions

View file

@ -1,6 +1,7 @@
#ifndef _NET_NF_TABLES_H
#define _NET_NF_TABLES_H
#include <linux/module.h>
#include <linux/list.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink.h>
@ -641,6 +642,18 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
return (void *)expr->data;
}
struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
const struct nlattr *nla);
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
const struct nft_expr *expr);
static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
{
__module_get(src->ops->type->owner);
memcpy(dst, src, src->ops->size);
}
/**
* struct nft_rule - nf_tables rule
*

View file

@ -1545,6 +1545,23 @@ static int nf_tables_fill_expr_info(struct sk_buff *skb,
return -1;
};
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
const struct nft_expr *expr)
{
struct nlattr *nest;
nest = nla_nest_start(skb, attr);
if (!nest)
goto nla_put_failure;
if (nf_tables_fill_expr_info(skb, expr) < 0)
goto nla_put_failure;
nla_nest_end(skb, nest);
return 0;
nla_put_failure:
return -1;
}
struct nft_expr_info {
const struct nft_expr_ops *ops;
struct nlattr *tb[NFT_EXPR_MAXATTR + 1];
@ -1622,6 +1639,39 @@ static void nf_tables_expr_destroy(const struct nft_ctx *ctx,
module_put(expr->ops->type->owner);
}
struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
const struct nlattr *nla)
{
struct nft_expr_info info;
struct nft_expr *expr;
int err;
err = nf_tables_expr_parse(ctx, nla, &info);
if (err < 0)
goto err1;
err = -ENOMEM;
expr = kzalloc(info.ops->size, GFP_KERNEL);
if (expr == NULL)
goto err2;
err = nf_tables_newexpr(ctx, &info, expr);
if (err < 0)
goto err2;
return expr;
err2:
module_put(info.ops->type->owner);
err1:
return ERR_PTR(err);
}
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr)
{
nf_tables_expr_destroy(ctx, expr);
kfree(expr);
}
/*
* Rules
*/
@ -1703,12 +1753,8 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
if (list == NULL)
goto nla_put_failure;
nft_rule_for_each_expr(expr, next, rule) {
struct nlattr *elem = nla_nest_start(skb, NFTA_LIST_ELEM);
if (elem == NULL)
if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
goto nla_put_failure;
if (nf_tables_fill_expr_info(skb, expr) < 0)
goto nla_put_failure;
nla_nest_end(skb, elem);
}
nla_nest_end(skb, list);