mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 04:36:41 +07:00
netfilter: nf_tables: add nf_tables_addchain()
Wrap the chain addition path in a function to make it more maintainable. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
2c4a488a48
commit
4035285fe0
@ -1335,6 +1335,106 @@ static void nft_chain_release_hook(struct nft_chain_hook *hook)
|
||||
dev_put(hook->dev);
|
||||
}
|
||||
|
||||
static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
|
||||
u8 policy, bool create)
|
||||
{
|
||||
const struct nlattr * const *nla = ctx->nla;
|
||||
struct nft_table *table = ctx->table;
|
||||
struct nft_af_info *afi = ctx->afi;
|
||||
struct nft_base_chain *basechain;
|
||||
struct nft_stats __percpu *stats;
|
||||
struct net *net = ctx->net;
|
||||
struct nft_chain *chain;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
if (table->use == UINT_MAX)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (nla[NFTA_CHAIN_HOOK]) {
|
||||
struct nft_chain_hook hook;
|
||||
struct nf_hook_ops *ops;
|
||||
nf_hookfn *hookfn;
|
||||
|
||||
err = nft_chain_parse_hook(net, nla, afi, &hook, create);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
|
||||
if (basechain == NULL) {
|
||||
nft_chain_release_hook(&hook);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (hook.dev != NULL)
|
||||
strncpy(basechain->dev_name, hook.dev->name, IFNAMSIZ);
|
||||
|
||||
if (nla[NFTA_CHAIN_COUNTERS]) {
|
||||
stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
|
||||
if (IS_ERR(stats)) {
|
||||
nft_chain_release_hook(&hook);
|
||||
kfree(basechain);
|
||||
return PTR_ERR(stats);
|
||||
}
|
||||
basechain->stats = stats;
|
||||
static_branch_inc(&nft_counters_enabled);
|
||||
}
|
||||
|
||||
hookfn = hook.type->hooks[hook.num];
|
||||
basechain->type = hook.type;
|
||||
chain = &basechain->chain;
|
||||
|
||||
for (i = 0; i < afi->nops; i++) {
|
||||
ops = &basechain->ops[i];
|
||||
ops->pf = family;
|
||||
ops->hooknum = hook.num;
|
||||
ops->priority = hook.priority;
|
||||
ops->priv = chain;
|
||||
ops->hook = afi->hooks[ops->hooknum];
|
||||
ops->dev = hook.dev;
|
||||
if (hookfn)
|
||||
ops->hook = hookfn;
|
||||
if (afi->hook_ops_init)
|
||||
afi->hook_ops_init(ops, i);
|
||||
}
|
||||
|
||||
chain->flags |= NFT_BASE_CHAIN;
|
||||
basechain->policy = policy;
|
||||
} else {
|
||||
chain = kzalloc(sizeof(*chain), GFP_KERNEL);
|
||||
if (chain == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_LIST_HEAD(&chain->rules);
|
||||
chain->handle = nf_tables_alloc_handle(table);
|
||||
chain->table = table;
|
||||
chain->name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
|
||||
if (!chain->name) {
|
||||
err = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
err = nf_tables_register_hooks(net, table, chain, afi->nops);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
ctx->chain = chain;
|
||||
err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
table->use++;
|
||||
list_add_tail_rcu(&chain->list, &table->chains);
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
nf_tables_unregister_hooks(net, table, chain, afi->nops);
|
||||
err1:
|
||||
nf_tables_chain_destroy(chain);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
|
||||
bool create)
|
||||
{
|
||||
@ -1433,19 +1533,15 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
||||
{
|
||||
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
||||
const struct nlattr * uninitialized_var(name);
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
struct nft_af_info *afi;
|
||||
struct nft_table *table;
|
||||
struct nft_chain *chain;
|
||||
struct nft_base_chain *basechain = NULL;
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
int family = nfmsg->nfgen_family;
|
||||
u8 policy = NF_ACCEPT;
|
||||
u64 handle = 0;
|
||||
unsigned int i;
|
||||
struct nft_stats __percpu *stats;
|
||||
int err;
|
||||
bool create;
|
||||
struct nft_ctx ctx;
|
||||
u64 handle = 0;
|
||||
bool create;
|
||||
|
||||
create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
|
||||
|
||||
@ -1493,101 +1589,18 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
||||
}
|
||||
}
|
||||
|
||||
nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
|
||||
|
||||
if (chain != NULL) {
|
||||
if (nlh->nlmsg_flags & NLM_F_EXCL)
|
||||
return -EEXIST;
|
||||
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
|
||||
|
||||
return nf_tables_updchain(&ctx, genmask, policy, create);
|
||||
}
|
||||
|
||||
if (table->use == UINT_MAX)
|
||||
return -EOVERFLOW;
|
||||
|
||||
if (nla[NFTA_CHAIN_HOOK]) {
|
||||
struct nft_chain_hook hook;
|
||||
struct nf_hook_ops *ops;
|
||||
nf_hookfn *hookfn;
|
||||
|
||||
err = nft_chain_parse_hook(net, nla, afi, &hook, create);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
|
||||
if (basechain == NULL) {
|
||||
nft_chain_release_hook(&hook);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (hook.dev != NULL)
|
||||
strncpy(basechain->dev_name, hook.dev->name, IFNAMSIZ);
|
||||
|
||||
if (nla[NFTA_CHAIN_COUNTERS]) {
|
||||
stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
|
||||
if (IS_ERR(stats)) {
|
||||
nft_chain_release_hook(&hook);
|
||||
kfree(basechain);
|
||||
return PTR_ERR(stats);
|
||||
}
|
||||
basechain->stats = stats;
|
||||
static_branch_inc(&nft_counters_enabled);
|
||||
}
|
||||
|
||||
hookfn = hook.type->hooks[hook.num];
|
||||
basechain->type = hook.type;
|
||||
chain = &basechain->chain;
|
||||
|
||||
for (i = 0; i < afi->nops; i++) {
|
||||
ops = &basechain->ops[i];
|
||||
ops->pf = family;
|
||||
ops->hooknum = hook.num;
|
||||
ops->priority = hook.priority;
|
||||
ops->priv = chain;
|
||||
ops->hook = afi->hooks[ops->hooknum];
|
||||
ops->dev = hook.dev;
|
||||
if (hookfn)
|
||||
ops->hook = hookfn;
|
||||
if (afi->hook_ops_init)
|
||||
afi->hook_ops_init(ops, i);
|
||||
}
|
||||
|
||||
chain->flags |= NFT_BASE_CHAIN;
|
||||
basechain->policy = policy;
|
||||
} else {
|
||||
chain = kzalloc(sizeof(*chain), GFP_KERNEL);
|
||||
if (chain == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&chain->rules);
|
||||
chain->handle = nf_tables_alloc_handle(table);
|
||||
chain->table = table;
|
||||
chain->name = nla_strdup(name, GFP_KERNEL);
|
||||
if (!chain->name) {
|
||||
err = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
err = nf_tables_register_hooks(net, table, chain, afi->nops);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
|
||||
err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
table->use++;
|
||||
list_add_tail_rcu(&chain->list, &table->chains);
|
||||
return 0;
|
||||
err2:
|
||||
nf_tables_unregister_hooks(net, table, chain, afi->nops);
|
||||
err1:
|
||||
nf_tables_chain_destroy(chain);
|
||||
return err;
|
||||
return nf_tables_addchain(&ctx, family, genmask, policy, create);
|
||||
}
|
||||
|
||||
static int nf_tables_delchain(struct net *net, struct sock *nlsk,
|
||||
|
Loading…
Reference in New Issue
Block a user