|
@@ -131,29 +131,8 @@ static void nft_trans_destroy(struct nft_trans *trans)
|
|
kfree(trans);
|
|
kfree(trans);
|
|
}
|
|
}
|
|
|
|
|
|
-static int nft_register_basechain(struct nft_base_chain *basechain,
|
|
|
|
- unsigned int hook_nops)
|
|
|
|
-{
|
|
|
|
- struct net *net = read_pnet(&basechain->pnet);
|
|
|
|
-
|
|
|
|
- if (basechain->flags & NFT_BASECHAIN_DISABLED)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- return nf_register_net_hooks(net, basechain->ops, hook_nops);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void nft_unregister_basechain(struct nft_base_chain *basechain,
|
|
|
|
- unsigned int hook_nops)
|
|
|
|
-{
|
|
|
|
- struct net *net = read_pnet(&basechain->pnet);
|
|
|
|
-
|
|
|
|
- if (basechain->flags & NFT_BASECHAIN_DISABLED)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- nf_unregister_net_hooks(net, basechain->ops, hook_nops);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int nf_tables_register_hooks(const struct nft_table *table,
|
|
|
|
|
|
+static int nf_tables_register_hooks(struct net *net,
|
|
|
|
+ const struct nft_table *table,
|
|
struct nft_chain *chain,
|
|
struct nft_chain *chain,
|
|
unsigned int hook_nops)
|
|
unsigned int hook_nops)
|
|
{
|
|
{
|
|
@@ -161,10 +140,12 @@ static int nf_tables_register_hooks(const struct nft_table *table,
|
|
!(chain->flags & NFT_BASE_CHAIN))
|
|
!(chain->flags & NFT_BASE_CHAIN))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- return nft_register_basechain(nft_base_chain(chain), hook_nops);
|
|
|
|
|
|
+ return nf_register_net_hooks(net, nft_base_chain(chain)->ops,
|
|
|
|
+ hook_nops);
|
|
}
|
|
}
|
|
|
|
|
|
-static void nf_tables_unregister_hooks(const struct nft_table *table,
|
|
|
|
|
|
+static void nf_tables_unregister_hooks(struct net *net,
|
|
|
|
+ const struct nft_table *table,
|
|
struct nft_chain *chain,
|
|
struct nft_chain *chain,
|
|
unsigned int hook_nops)
|
|
unsigned int hook_nops)
|
|
{
|
|
{
|
|
@@ -172,12 +153,9 @@ static void nf_tables_unregister_hooks(const struct nft_table *table,
|
|
!(chain->flags & NFT_BASE_CHAIN))
|
|
!(chain->flags & NFT_BASE_CHAIN))
|
|
return;
|
|
return;
|
|
|
|
|
|
- nft_unregister_basechain(nft_base_chain(chain), hook_nops);
|
|
|
|
|
|
+ nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops);
|
|
}
|
|
}
|
|
|
|
|
|
-/* Internal table flags */
|
|
|
|
-#define NFT_TABLE_INACTIVE (1 << 15)
|
|
|
|
-
|
|
|
|
static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
|
|
static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
|
|
{
|
|
{
|
|
struct nft_trans *trans;
|
|
struct nft_trans *trans;
|
|
@@ -187,7 +165,7 @@ static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
if (msg_type == NFT_MSG_NEWTABLE)
|
|
if (msg_type == NFT_MSG_NEWTABLE)
|
|
- ctx->table->flags |= NFT_TABLE_INACTIVE;
|
|
|
|
|
|
+ nft_activate_next(ctx->net, ctx->table);
|
|
|
|
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
return 0;
|
|
return 0;
|
|
@@ -201,7 +179,7 @@ static int nft_deltable(struct nft_ctx *ctx)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- list_del_rcu(&ctx->table->list);
|
|
|
|
|
|
+ nft_deactivate_next(ctx->net, ctx->table);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -214,7 +192,7 @@ static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
if (msg_type == NFT_MSG_NEWCHAIN)
|
|
if (msg_type == NFT_MSG_NEWCHAIN)
|
|
- ctx->chain->flags |= NFT_CHAIN_INACTIVE;
|
|
|
|
|
|
+ nft_activate_next(ctx->net, ctx->chain);
|
|
|
|
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
return 0;
|
|
return 0;
|
|
@@ -229,47 +207,17 @@ static int nft_delchain(struct nft_ctx *ctx)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
ctx->table->use--;
|
|
ctx->table->use--;
|
|
- list_del_rcu(&ctx->chain->list);
|
|
|
|
|
|
+ nft_deactivate_next(ctx->net, ctx->chain);
|
|
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-static inline bool
|
|
|
|
-nft_rule_is_active(struct net *net, const struct nft_rule *rule)
|
|
|
|
-{
|
|
|
|
- return (rule->genmask & nft_genmask_cur(net)) == 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline int
|
|
|
|
-nft_rule_is_active_next(struct net *net, const struct nft_rule *rule)
|
|
|
|
-{
|
|
|
|
- return (rule->genmask & nft_genmask_next(net)) == 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline void
|
|
|
|
-nft_rule_activate_next(struct net *net, struct nft_rule *rule)
|
|
|
|
-{
|
|
|
|
- /* Now inactive, will be active in the future */
|
|
|
|
- rule->genmask = nft_genmask_cur(net);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline void
|
|
|
|
-nft_rule_deactivate_next(struct net *net, struct nft_rule *rule)
|
|
|
|
-{
|
|
|
|
- rule->genmask = nft_genmask_next(net);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static inline void nft_rule_clear(struct net *net, struct nft_rule *rule)
|
|
|
|
-{
|
|
|
|
- rule->genmask &= ~nft_genmask_next(net);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int
|
|
static int
|
|
nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
{
|
|
{
|
|
/* You cannot delete the same rule twice */
|
|
/* You cannot delete the same rule twice */
|
|
- if (nft_rule_is_active_next(ctx->net, rule)) {
|
|
|
|
- nft_rule_deactivate_next(ctx->net, rule);
|
|
|
|
|
|
+ if (nft_is_active_next(ctx->net, rule)) {
|
|
|
|
+ nft_deactivate_next(ctx->net, rule);
|
|
ctx->chain->use--;
|
|
ctx->chain->use--;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -322,9 +270,6 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* Internal set flag */
|
|
|
|
-#define NFT_SET_INACTIVE (1 << 15)
|
|
|
|
-
|
|
|
|
static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
|
|
static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
|
|
struct nft_set *set)
|
|
struct nft_set *set)
|
|
{
|
|
{
|
|
@@ -337,7 +282,7 @@ static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
|
|
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
|
|
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
|
|
nft_trans_set_id(trans) =
|
|
nft_trans_set_id(trans) =
|
|
ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
|
|
ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
|
|
- set->flags |= NFT_SET_INACTIVE;
|
|
|
|
|
|
+ nft_activate_next(ctx->net, set);
|
|
}
|
|
}
|
|
nft_trans_set(trans) = set;
|
|
nft_trans_set(trans) = set;
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
@@ -353,7 +298,7 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- list_del_rcu(&set->list);
|
|
|
|
|
|
+ nft_deactivate_next(ctx->net, set);
|
|
ctx->table->use--;
|
|
ctx->table->use--;
|
|
|
|
|
|
return err;
|
|
return err;
|
|
@@ -364,26 +309,29 @@ static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
|
|
*/
|
|
*/
|
|
|
|
|
|
static struct nft_table *nft_table_lookup(const struct nft_af_info *afi,
|
|
static struct nft_table *nft_table_lookup(const struct nft_af_info *afi,
|
|
- const struct nlattr *nla)
|
|
|
|
|
|
+ const struct nlattr *nla,
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
|
|
|
|
list_for_each_entry(table, &afi->tables, list) {
|
|
list_for_each_entry(table, &afi->tables, list) {
|
|
- if (!nla_strcmp(nla, table->name))
|
|
|
|
|
|
+ if (!nla_strcmp(nla, table->name) &&
|
|
|
|
+ nft_active_genmask(table, genmask))
|
|
return table;
|
|
return table;
|
|
}
|
|
}
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi,
|
|
static struct nft_table *nf_tables_table_lookup(const struct nft_af_info *afi,
|
|
- const struct nlattr *nla)
|
|
|
|
|
|
+ const struct nlattr *nla,
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
|
|
|
|
if (nla == NULL)
|
|
if (nla == NULL)
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
- table = nft_table_lookup(afi, nla);
|
|
|
|
|
|
+ table = nft_table_lookup(afi, nla, genmask);
|
|
if (table != NULL)
|
|
if (table != NULL)
|
|
return table;
|
|
return table;
|
|
|
|
|
|
@@ -524,6 +472,8 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
|
|
if (idx > s_idx)
|
|
if (idx > s_idx)
|
|
memset(&cb->args[1], 0,
|
|
memset(&cb->args[1], 0,
|
|
sizeof(cb->args) - sizeof(cb->args[0]));
|
|
sizeof(cb->args) - sizeof(cb->args[0]));
|
|
|
|
+ if (!nft_is_active(net, table))
|
|
|
|
+ continue;
|
|
if (nf_tables_fill_table_info(skb, net,
|
|
if (nf_tables_fill_table_info(skb, net,
|
|
NETLINK_CB(cb->skb).portid,
|
|
NETLINK_CB(cb->skb).portid,
|
|
cb->nlh->nlmsg_seq,
|
|
cb->nlh->nlmsg_seq,
|
|
@@ -548,6 +498,7 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_af_info *afi;
|
|
const struct nft_af_info *afi;
|
|
const struct nft_table *table;
|
|
const struct nft_table *table;
|
|
struct sk_buff *skb2;
|
|
struct sk_buff *skb2;
|
|
@@ -565,11 +516,9 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
- if (table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
if (!skb2)
|
|
if (!skb2)
|
|
@@ -588,17 +537,21 @@ err:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-static int nf_tables_table_enable(const struct nft_af_info *afi,
|
|
|
|
|
|
+static int nf_tables_table_enable(struct net *net,
|
|
|
|
+ const struct nft_af_info *afi,
|
|
struct nft_table *table)
|
|
struct nft_table *table)
|
|
{
|
|
{
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
int err, i = 0;
|
|
int err, i = 0;
|
|
|
|
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
|
|
+ if (!nft_is_active_next(net, chain))
|
|
|
|
+ continue;
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- err = nft_register_basechain(nft_base_chain(chain), afi->nops);
|
|
|
|
|
|
+ err = nf_register_net_hooks(net, nft_base_chain(chain)->ops,
|
|
|
|
+ afi->nops);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
@@ -607,26 +560,34 @@ static int nf_tables_table_enable(const struct nft_af_info *afi,
|
|
return 0;
|
|
return 0;
|
|
err:
|
|
err:
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
|
|
+ if (!nft_is_active_next(net, chain))
|
|
|
|
+ continue;
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if (i-- <= 0)
|
|
if (i-- <= 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
- nft_unregister_basechain(nft_base_chain(chain), afi->nops);
|
|
|
|
|
|
+ nf_unregister_net_hooks(net, nft_base_chain(chain)->ops,
|
|
|
|
+ afi->nops);
|
|
}
|
|
}
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-static void nf_tables_table_disable(const struct nft_af_info *afi,
|
|
|
|
|
|
+static void nf_tables_table_disable(struct net *net,
|
|
|
|
+ const struct nft_af_info *afi,
|
|
struct nft_table *table)
|
|
struct nft_table *table)
|
|
{
|
|
{
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
|
|
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
- if (chain->flags & NFT_BASE_CHAIN)
|
|
|
|
- nft_unregister_basechain(nft_base_chain(chain),
|
|
|
|
- afi->nops);
|
|
|
|
|
|
+ if (!nft_is_active_next(net, chain))
|
|
|
|
+ continue;
|
|
|
|
+ if (!(chain->flags & NFT_BASE_CHAIN))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ nf_unregister_net_hooks(net, nft_base_chain(chain)->ops,
|
|
|
|
+ afi->nops);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -656,7 +617,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
|
|
nft_trans_table_enable(trans) = false;
|
|
nft_trans_table_enable(trans) = false;
|
|
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
|
|
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
|
|
ctx->table->flags & NFT_TABLE_F_DORMANT) {
|
|
ctx->table->flags & NFT_TABLE_F_DORMANT) {
|
|
- ret = nf_tables_table_enable(ctx->afi, ctx->table);
|
|
|
|
|
|
+ ret = nf_tables_table_enable(ctx->net, ctx->afi, ctx->table);
|
|
if (ret >= 0) {
|
|
if (ret >= 0) {
|
|
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
|
|
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
|
|
nft_trans_table_enable(trans) = true;
|
|
nft_trans_table_enable(trans) = true;
|
|
@@ -678,6 +639,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
const struct nlattr *name;
|
|
const struct nlattr *name;
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
@@ -691,7 +653,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
name = nla[NFTA_TABLE_NAME];
|
|
name = nla[NFTA_TABLE_NAME];
|
|
- table = nf_tables_table_lookup(afi, name);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, name, genmask);
|
|
if (IS_ERR(table)) {
|
|
if (IS_ERR(table)) {
|
|
if (PTR_ERR(table) != -ENOENT)
|
|
if (PTR_ERR(table) != -ENOENT)
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
@@ -699,8 +661,6 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
|
|
}
|
|
}
|
|
|
|
|
|
if (table != NULL) {
|
|
if (table != NULL) {
|
|
- if (table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_EXCL)
|
|
if (nlh->nlmsg_flags & NLM_F_EXCL)
|
|
return -EEXIST;
|
|
return -EEXIST;
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
|
@@ -752,6 +712,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
|
|
struct nft_set *set, *ns;
|
|
struct nft_set *set, *ns;
|
|
|
|
|
|
list_for_each_entry(chain, &ctx->table->chains, list) {
|
|
list_for_each_entry(chain, &ctx->table->chains, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, chain))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
ctx->chain = chain;
|
|
ctx->chain = chain;
|
|
|
|
|
|
err = nft_delrule_by_chain(ctx);
|
|
err = nft_delrule_by_chain(ctx);
|
|
@@ -760,6 +723,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
|
|
}
|
|
}
|
|
|
|
|
|
list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
|
|
list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, set))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
if (set->flags & NFT_SET_ANONYMOUS &&
|
|
if (set->flags & NFT_SET_ANONYMOUS &&
|
|
!list_empty(&set->bindings))
|
|
!list_empty(&set->bindings))
|
|
continue;
|
|
continue;
|
|
@@ -770,6 +736,9 @@ static int nft_flush_table(struct nft_ctx *ctx)
|
|
}
|
|
}
|
|
|
|
|
|
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
|
|
list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, chain))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
ctx->chain = chain;
|
|
ctx->chain = chain;
|
|
|
|
|
|
err = nft_delchain(ctx);
|
|
err = nft_delchain(ctx);
|
|
@@ -795,6 +764,9 @@ static int nft_flush(struct nft_ctx *ctx, int family)
|
|
|
|
|
|
ctx->afi = afi;
|
|
ctx->afi = afi;
|
|
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
|
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, table))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
if (nla[NFTA_TABLE_NAME] &&
|
|
if (nla[NFTA_TABLE_NAME] &&
|
|
nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
|
|
nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
|
|
continue;
|
|
continue;
|
|
@@ -815,6 +787,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
int family = nfmsg->nfgen_family;
|
|
int family = nfmsg->nfgen_family;
|
|
@@ -828,7 +801,7 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_TABLE_NAME], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
@@ -875,12 +848,14 @@ EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
|
|
*/
|
|
*/
|
|
|
|
|
|
static struct nft_chain *
|
|
static struct nft_chain *
|
|
-nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle)
|
|
|
|
|
|
+nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle,
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
|
|
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
- if (chain->handle == handle)
|
|
|
|
|
|
+ if (chain->handle == handle &&
|
|
|
|
+ nft_active_genmask(chain, genmask))
|
|
return chain;
|
|
return chain;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -888,7 +863,8 @@ nf_tables_chain_lookup_byhandle(const struct nft_table *table, u64 handle)
|
|
}
|
|
}
|
|
|
|
|
|
static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
|
|
static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
|
|
- const struct nlattr *nla)
|
|
|
|
|
|
+ const struct nlattr *nla,
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
|
|
|
|
@@ -896,7 +872,8 @@ static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
- if (!nla_strcmp(nla, chain->name))
|
|
|
|
|
|
+ if (!nla_strcmp(nla, chain->name) &&
|
|
|
|
+ nft_active_genmask(chain, genmask))
|
|
return chain;
|
|
return chain;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1079,6 +1056,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
|
|
if (idx > s_idx)
|
|
if (idx > s_idx)
|
|
memset(&cb->args[1], 0,
|
|
memset(&cb->args[1], 0,
|
|
sizeof(cb->args) - sizeof(cb->args[0]));
|
|
sizeof(cb->args) - sizeof(cb->args[0]));
|
|
|
|
+ if (!nft_is_active(net, chain))
|
|
|
|
+ continue;
|
|
if (nf_tables_fill_chain_info(skb, net,
|
|
if (nf_tables_fill_chain_info(skb, net,
|
|
NETLINK_CB(cb->skb).portid,
|
|
NETLINK_CB(cb->skb).portid,
|
|
cb->nlh->nlmsg_seq,
|
|
cb->nlh->nlmsg_seq,
|
|
@@ -1104,6 +1083,7 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_af_info *afi;
|
|
const struct nft_af_info *afi;
|
|
const struct nft_table *table;
|
|
const struct nft_table *table;
|
|
const struct nft_chain *chain;
|
|
const struct nft_chain *chain;
|
|
@@ -1122,17 +1102,13 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
- if (table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
- chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
- if (chain->flags & NFT_CHAIN_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
if (!skb2)
|
|
if (!skb2)
|
|
@@ -1231,6 +1207,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
struct nft_base_chain *basechain = NULL;
|
|
struct nft_base_chain *basechain = NULL;
|
|
struct nlattr *ha[NFTA_HOOK_MAX + 1];
|
|
struct nlattr *ha[NFTA_HOOK_MAX + 1];
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
int family = nfmsg->nfgen_family;
|
|
int family = nfmsg->nfgen_family;
|
|
struct net_device *dev = NULL;
|
|
struct net_device *dev = NULL;
|
|
u8 policy = NF_ACCEPT;
|
|
u8 policy = NF_ACCEPT;
|
|
@@ -1247,7 +1224,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
@@ -1256,11 +1233,11 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
|
|
|
|
if (nla[NFTA_CHAIN_HANDLE]) {
|
|
if (nla[NFTA_CHAIN_HANDLE]) {
|
|
handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
|
|
handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
|
|
- chain = nf_tables_chain_lookup_byhandle(table, handle);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup_byhandle(table, handle, genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
} else {
|
|
} else {
|
|
- chain = nf_tables_chain_lookup(table, name);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, name, genmask);
|
|
if (IS_ERR(chain)) {
|
|
if (IS_ERR(chain)) {
|
|
if (PTR_ERR(chain) != -ENOENT)
|
|
if (PTR_ERR(chain) != -ENOENT)
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
@@ -1291,16 +1268,20 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
struct nft_stats *stats = NULL;
|
|
struct nft_stats *stats = NULL;
|
|
struct nft_trans *trans;
|
|
struct nft_trans *trans;
|
|
|
|
|
|
- if (chain->flags & NFT_CHAIN_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_EXCL)
|
|
if (nlh->nlmsg_flags & NLM_F_EXCL)
|
|
return -EEXIST;
|
|
return -EEXIST;
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE)
|
|
return -EOPNOTSUPP;
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
- if (nla[NFTA_CHAIN_HANDLE] && name &&
|
|
|
|
- !IS_ERR(nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME])))
|
|
|
|
- return -EEXIST;
|
|
|
|
|
|
+ if (nla[NFTA_CHAIN_HANDLE] && name) {
|
|
|
|
+ struct nft_chain *chain2;
|
|
|
|
+
|
|
|
|
+ chain2 = nf_tables_chain_lookup(table,
|
|
|
|
+ nla[NFTA_CHAIN_NAME],
|
|
|
|
+ genmask);
|
|
|
|
+ if (IS_ERR(chain2))
|
|
|
|
+ return PTR_ERR(chain2);
|
|
|
|
+ }
|
|
|
|
|
|
if (nla[NFTA_CHAIN_COUNTERS]) {
|
|
if (nla[NFTA_CHAIN_COUNTERS]) {
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
if (!(chain->flags & NFT_BASE_CHAIN))
|
|
@@ -1455,7 +1436,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
chain->table = table;
|
|
chain->table = table;
|
|
nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN);
|
|
nla_strlcpy(chain->name, name, NFT_CHAIN_MAXNAMELEN);
|
|
|
|
|
|
- err = nf_tables_register_hooks(table, chain, afi->nops);
|
|
|
|
|
|
+ err = nf_tables_register_hooks(net, table, chain, afi->nops);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto err1;
|
|
goto err1;
|
|
|
|
|
|
@@ -1468,7 +1449,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
|
|
list_add_tail_rcu(&chain->list, &table->chains);
|
|
list_add_tail_rcu(&chain->list, &table->chains);
|
|
return 0;
|
|
return 0;
|
|
err2:
|
|
err2:
|
|
- nf_tables_unregister_hooks(table, chain, afi->nops);
|
|
|
|
|
|
+ nf_tables_unregister_hooks(net, table, chain, afi->nops);
|
|
err1:
|
|
err1:
|
|
nf_tables_chain_destroy(chain);
|
|
nf_tables_chain_destroy(chain);
|
|
return err;
|
|
return err;
|
|
@@ -1479,6 +1460,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
@@ -1489,11 +1471,11 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_CHAIN_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
- chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME]);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
if (chain->use > 0)
|
|
if (chain->use > 0)
|
|
@@ -1898,7 +1880,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
|
|
list_for_each_entry_rcu(table, &afi->tables, list) {
|
|
list_for_each_entry_rcu(table, &afi->tables, list) {
|
|
list_for_each_entry_rcu(chain, &table->chains, list) {
|
|
list_for_each_entry_rcu(chain, &table->chains, list) {
|
|
list_for_each_entry_rcu(rule, &chain->rules, list) {
|
|
list_for_each_entry_rcu(rule, &chain->rules, list) {
|
|
- if (!nft_rule_is_active(net, rule))
|
|
|
|
|
|
+ if (!nft_is_active(net, rule))
|
|
goto cont;
|
|
goto cont;
|
|
if (idx < s_idx)
|
|
if (idx < s_idx)
|
|
goto cont;
|
|
goto cont;
|
|
@@ -1931,6 +1913,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_af_info *afi;
|
|
const struct nft_af_info *afi;
|
|
const struct nft_table *table;
|
|
const struct nft_table *table;
|
|
const struct nft_chain *chain;
|
|
const struct nft_chain *chain;
|
|
@@ -1950,17 +1933,13 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
- if (table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
- chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
- if (chain->flags & NFT_CHAIN_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
|
|
rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
|
|
if (IS_ERR(rule))
|
|
if (IS_ERR(rule))
|
|
@@ -2009,6 +1988,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
@@ -2029,11 +2009,11 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
- chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN], genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
|
|
|
|
@@ -2102,7 +2082,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
|
|
if (rule == NULL)
|
|
if (rule == NULL)
|
|
goto err1;
|
|
goto err1;
|
|
|
|
|
|
- nft_rule_activate_next(net, rule);
|
|
|
|
|
|
+ nft_activate_next(net, rule);
|
|
|
|
|
|
rule->handle = handle;
|
|
rule->handle = handle;
|
|
rule->dlen = size;
|
|
rule->dlen = size;
|
|
@@ -2124,14 +2104,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
|
|
}
|
|
}
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
|
|
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
|
|
- if (nft_rule_is_active_next(net, old_rule)) {
|
|
|
|
|
|
+ if (nft_is_active_next(net, old_rule)) {
|
|
trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
|
|
trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
|
|
old_rule);
|
|
old_rule);
|
|
if (trans == NULL) {
|
|
if (trans == NULL) {
|
|
err = -ENOMEM;
|
|
err = -ENOMEM;
|
|
goto err2;
|
|
goto err2;
|
|
}
|
|
}
|
|
- nft_rule_deactivate_next(net, old_rule);
|
|
|
|
|
|
+ nft_deactivate_next(net, old_rule);
|
|
chain->use--;
|
|
chain->use--;
|
|
list_add_tail_rcu(&rule->list, &old_rule->list);
|
|
list_add_tail_rcu(&rule->list, &old_rule->list);
|
|
} else {
|
|
} else {
|
|
@@ -2174,6 +2154,7 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
struct nft_chain *chain = NULL;
|
|
struct nft_chain *chain = NULL;
|
|
@@ -2185,12 +2166,13 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_RULE_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
if (nla[NFTA_RULE_CHAIN]) {
|
|
if (nla[NFTA_RULE_CHAIN]) {
|
|
- chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN]);
|
|
|
|
|
|
+ chain = nf_tables_chain_lookup(table, nla[NFTA_RULE_CHAIN],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
}
|
|
}
|
|
@@ -2210,6 +2192,9 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
|
|
+ if (!nft_is_active_next(net, chain))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
ctx.chain = chain;
|
|
ctx.chain = chain;
|
|
err = nft_delrule_by_chain(&ctx);
|
|
err = nft_delrule_by_chain(&ctx);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -2339,7 +2324,8 @@ static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
|
|
static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
|
|
static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
|
|
const struct sk_buff *skb,
|
|
const struct sk_buff *skb,
|
|
const struct nlmsghdr *nlh,
|
|
const struct nlmsghdr *nlh,
|
|
- const struct nlattr * const nla[])
|
|
|
|
|
|
+ const struct nlattr * const nla[],
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
struct nft_af_info *afi = NULL;
|
|
struct nft_af_info *afi = NULL;
|
|
@@ -2355,7 +2341,8 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
|
|
if (afi == NULL)
|
|
if (afi == NULL)
|
|
return -EAFNOSUPPORT;
|
|
return -EAFNOSUPPORT;
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
}
|
|
}
|
|
@@ -2365,7 +2352,7 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
|
|
}
|
|
}
|
|
|
|
|
|
struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
|
struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
|
- const struct nlattr *nla)
|
|
|
|
|
|
+ const struct nlattr *nla, u8 genmask)
|
|
{
|
|
{
|
|
struct nft_set *set;
|
|
struct nft_set *set;
|
|
|
|
|
|
@@ -2373,22 +2360,27 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
list_for_each_entry(set, &table->sets, list) {
|
|
list_for_each_entry(set, &table->sets, list) {
|
|
- if (!nla_strcmp(nla, set->name))
|
|
|
|
|
|
+ if (!nla_strcmp(nla, set->name) &&
|
|
|
|
+ nft_active_genmask(set, genmask))
|
|
return set;
|
|
return set;
|
|
}
|
|
}
|
|
return ERR_PTR(-ENOENT);
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
}
|
|
|
|
|
|
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
|
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
|
- const struct nlattr *nla)
|
|
|
|
|
|
+ const struct nlattr *nla,
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
struct nft_trans *trans;
|
|
struct nft_trans *trans;
|
|
u32 id = ntohl(nla_get_be32(nla));
|
|
u32 id = ntohl(nla_get_be32(nla));
|
|
|
|
|
|
list_for_each_entry(trans, &net->nft.commit_list, list) {
|
|
list_for_each_entry(trans, &net->nft.commit_list, list) {
|
|
|
|
+ struct nft_set *set = nft_trans_set(trans);
|
|
|
|
+
|
|
if (trans->msg_type == NFT_MSG_NEWSET &&
|
|
if (trans->msg_type == NFT_MSG_NEWSET &&
|
|
- id == nft_trans_set_id(trans))
|
|
|
|
- return nft_trans_set(trans);
|
|
|
|
|
|
+ id == nft_trans_set_id(trans) &&
|
|
|
|
+ nft_active_genmask(set, genmask))
|
|
|
|
+ return set;
|
|
}
|
|
}
|
|
return ERR_PTR(-ENOENT);
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
}
|
|
@@ -2413,6 +2405,8 @@ cont:
|
|
list_for_each_entry(i, &ctx->table->sets, list) {
|
|
list_for_each_entry(i, &ctx->table->sets, list) {
|
|
int tmp;
|
|
int tmp;
|
|
|
|
|
|
|
|
+ if (!nft_is_active_next(ctx->net, set))
|
|
|
|
+ continue;
|
|
if (!sscanf(i->name, name, &tmp))
|
|
if (!sscanf(i->name, name, &tmp))
|
|
continue;
|
|
continue;
|
|
if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
|
|
if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
|
|
@@ -2432,6 +2426,8 @@ cont:
|
|
|
|
|
|
snprintf(set->name, sizeof(set->name), name, min + n);
|
|
snprintf(set->name, sizeof(set->name), name, min + n);
|
|
list_for_each_entry(i, &ctx->table->sets, list) {
|
|
list_for_each_entry(i, &ctx->table->sets, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, i))
|
|
|
|
+ continue;
|
|
if (!strcmp(set->name, i->name))
|
|
if (!strcmp(set->name, i->name))
|
|
return -ENFILE;
|
|
return -ENFILE;
|
|
}
|
|
}
|
|
@@ -2580,6 +2576,8 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
|
|
list_for_each_entry_rcu(set, &table->sets, list) {
|
|
list_for_each_entry_rcu(set, &table->sets, list) {
|
|
if (idx < s_idx)
|
|
if (idx < s_idx)
|
|
goto cont;
|
|
goto cont;
|
|
|
|
+ if (!nft_is_active(net, set))
|
|
|
|
+ goto cont;
|
|
|
|
|
|
ctx_set = *ctx;
|
|
ctx_set = *ctx;
|
|
ctx_set.table = table;
|
|
ctx_set.table = table;
|
|
@@ -2616,6 +2614,7 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_set *set;
|
|
const struct nft_set *set;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
struct sk_buff *skb2;
|
|
struct sk_buff *skb2;
|
|
@@ -2623,7 +2622,7 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
|
int err;
|
|
int err;
|
|
|
|
|
|
/* Verify existence before starting dump */
|
|
/* Verify existence before starting dump */
|
|
- err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
|
|
|
|
|
|
+ err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
@@ -2650,11 +2649,9 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
|
if (!nla[NFTA_SET_TABLE])
|
|
if (!nla[NFTA_SET_TABLE])
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
- if (set->flags & NFT_SET_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
if (skb2 == NULL)
|
|
if (skb2 == NULL)
|
|
@@ -2693,6 +2690,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
const struct nft_set_ops *ops;
|
|
const struct nft_set_ops *ops;
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
struct nft_table *table;
|
|
struct nft_table *table;
|
|
@@ -2790,13 +2788,13 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE], genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
|
|
nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
|
|
|
|
|
|
- set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME], genmask);
|
|
if (IS_ERR(set)) {
|
|
if (IS_ERR(set)) {
|
|
if (PTR_ERR(set) != -ENOENT)
|
|
if (PTR_ERR(set) != -ENOENT)
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
@@ -2895,6 +2893,7 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
struct nft_set *set;
|
|
struct nft_set *set;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
int err;
|
|
int err;
|
|
@@ -2904,11 +2903,11 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
|
|
if (nla[NFTA_SET_TABLE] == NULL)
|
|
if (nla[NFTA_SET_TABLE] == NULL)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
|
|
|
|
|
|
+ err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
if (!list_empty(&set->bindings))
|
|
if (!list_empty(&set->bindings))
|
|
@@ -2973,7 +2972,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|
list_del_rcu(&binding->list);
|
|
list_del_rcu(&binding->list);
|
|
|
|
|
|
if (list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS &&
|
|
if (list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS &&
|
|
- !(set->flags & NFT_SET_INACTIVE))
|
|
|
|
|
|
+ nft_is_active(ctx->net, set))
|
|
nf_tables_set_destroy(ctx, set);
|
|
nf_tables_set_destroy(ctx, set);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3029,7 +3028,8 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
|
|
static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
|
|
static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
|
|
const struct sk_buff *skb,
|
|
const struct sk_buff *skb,
|
|
const struct nlmsghdr *nlh,
|
|
const struct nlmsghdr *nlh,
|
|
- const struct nlattr * const nla[])
|
|
|
|
|
|
+ const struct nlattr * const nla[],
|
|
|
|
+ u8 genmask)
|
|
{
|
|
{
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
|
|
struct nft_af_info *afi;
|
|
struct nft_af_info *afi;
|
|
@@ -3039,7 +3039,8 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
|
|
if (IS_ERR(afi))
|
|
if (IS_ERR(afi))
|
|
return PTR_ERR(afi);
|
|
return PTR_ERR(afi);
|
|
|
|
|
|
- table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE]);
|
|
|
|
|
|
+ table = nf_tables_table_lookup(afi, nla[NFTA_SET_ELEM_LIST_TABLE],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(table))
|
|
if (IS_ERR(table))
|
|
return PTR_ERR(table);
|
|
return PTR_ERR(table);
|
|
|
|
|
|
@@ -3136,6 +3137,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
|
|
static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
|
static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
|
{
|
|
{
|
|
struct net *net = sock_net(skb->sk);
|
|
struct net *net = sock_net(skb->sk);
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_set *set;
|
|
const struct nft_set *set;
|
|
struct nft_set_dump_args args;
|
|
struct nft_set_dump_args args;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
@@ -3152,17 +3154,14 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
|
|
err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
|
|
- (void *)nla);
|
|
|
|
|
|
+ (void *)nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
- if (ctx.table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
- if (set->flags & NFT_SET_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
event = NFT_MSG_NEWSETELEM;
|
|
event = NFT_MSG_NEWSETELEM;
|
|
event |= NFNL_SUBSYS_NFTABLES << 8;
|
|
event |= NFNL_SUBSYS_NFTABLES << 8;
|
|
@@ -3216,21 +3215,19 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
|
|
+ u8 genmask = nft_genmask_cur(net);
|
|
const struct nft_set *set;
|
|
const struct nft_set *set;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
|
|
|
|
|
|
+ err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
- if (ctx.table->flags & NFT_TABLE_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
- if (set->flags & NFT_SET_INACTIVE)
|
|
|
|
- return -ENOENT;
|
|
|
|
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
struct netlink_dump_control c = {
|
|
struct netlink_dump_control c = {
|
|
@@ -3548,6 +3545,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
const struct nlattr *attr;
|
|
const struct nlattr *attr;
|
|
struct nft_set *set;
|
|
struct nft_set *set;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
@@ -3556,15 +3554,17 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
|
|
if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
|
|
|
|
|
|
+ err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(set)) {
|
|
if (IS_ERR(set)) {
|
|
if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
|
|
if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
|
|
set = nf_tables_set_lookup_byid(net,
|
|
set = nf_tables_set_lookup_byid(net,
|
|
- nla[NFTA_SET_ELEM_LIST_SET_ID]);
|
|
|
|
|
|
+ nla[NFTA_SET_ELEM_LIST_SET_ID],
|
|
|
|
+ genmask);
|
|
}
|
|
}
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
@@ -3670,6 +3670,7 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
struct sk_buff *skb, const struct nlmsghdr *nlh,
|
|
const struct nlattr * const nla[])
|
|
const struct nlattr * const nla[])
|
|
{
|
|
{
|
|
|
|
+ u8 genmask = nft_genmask_next(net);
|
|
const struct nlattr *attr;
|
|
const struct nlattr *attr;
|
|
struct nft_set *set;
|
|
struct nft_set *set;
|
|
struct nft_ctx ctx;
|
|
struct nft_ctx ctx;
|
|
@@ -3678,11 +3679,12 @@ static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
|
|
if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla);
|
|
|
|
|
|
+ err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, genmask);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
- set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET]);
|
|
|
|
|
|
+ set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
|
|
|
|
+ genmask);
|
|
if (IS_ERR(set))
|
|
if (IS_ERR(set))
|
|
return PTR_ERR(set);
|
|
return PTR_ERR(set);
|
|
if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
|
|
if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
|
|
@@ -3950,36 +3952,40 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|
case NFT_MSG_NEWTABLE:
|
|
case NFT_MSG_NEWTABLE:
|
|
if (nft_trans_table_update(trans)) {
|
|
if (nft_trans_table_update(trans)) {
|
|
if (!nft_trans_table_enable(trans)) {
|
|
if (!nft_trans_table_enable(trans)) {
|
|
- nf_tables_table_disable(trans->ctx.afi,
|
|
|
|
|
|
+ nf_tables_table_disable(net,
|
|
|
|
+ trans->ctx.afi,
|
|
trans->ctx.table);
|
|
trans->ctx.table);
|
|
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
|
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- trans->ctx.table->flags &= ~NFT_TABLE_INACTIVE;
|
|
|
|
|
|
+ nft_clear(net, trans->ctx.table);
|
|
}
|
|
}
|
|
nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
|
|
nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELTABLE:
|
|
case NFT_MSG_DELTABLE:
|
|
|
|
+ list_del_rcu(&trans->ctx.table->list);
|
|
nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
|
|
nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWCHAIN:
|
|
case NFT_MSG_NEWCHAIN:
|
|
if (nft_trans_chain_update(trans))
|
|
if (nft_trans_chain_update(trans))
|
|
nft_chain_commit_update(trans);
|
|
nft_chain_commit_update(trans);
|
|
else
|
|
else
|
|
- trans->ctx.chain->flags &= ~NFT_CHAIN_INACTIVE;
|
|
|
|
|
|
+ nft_clear(net, trans->ctx.chain);
|
|
|
|
|
|
nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
|
|
nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELCHAIN:
|
|
case NFT_MSG_DELCHAIN:
|
|
|
|
+ list_del_rcu(&trans->ctx.chain->list);
|
|
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
|
|
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
|
|
- nf_tables_unregister_hooks(trans->ctx.table,
|
|
|
|
|
|
+ nf_tables_unregister_hooks(trans->ctx.net,
|
|
|
|
+ trans->ctx.table,
|
|
trans->ctx.chain,
|
|
trans->ctx.chain,
|
|
trans->ctx.afi->nops);
|
|
trans->ctx.afi->nops);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWRULE:
|
|
case NFT_MSG_NEWRULE:
|
|
- nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
|
|
|
|
+ nft_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
nf_tables_rule_notify(&trans->ctx,
|
|
nf_tables_rule_notify(&trans->ctx,
|
|
nft_trans_rule(trans),
|
|
nft_trans_rule(trans),
|
|
NFT_MSG_NEWRULE);
|
|
NFT_MSG_NEWRULE);
|
|
@@ -3992,7 +3998,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|
NFT_MSG_DELRULE);
|
|
NFT_MSG_DELRULE);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWSET:
|
|
case NFT_MSG_NEWSET:
|
|
- nft_trans_set(trans)->flags &= ~NFT_SET_INACTIVE;
|
|
|
|
|
|
+ nft_clear(net, nft_trans_set(trans));
|
|
/* This avoids hitting -EBUSY when deleting the table
|
|
/* This avoids hitting -EBUSY when deleting the table
|
|
* from the transaction.
|
|
* from the transaction.
|
|
*/
|
|
*/
|
|
@@ -4005,6 +4011,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELSET:
|
|
case NFT_MSG_DELSET:
|
|
|
|
+ list_del_rcu(&nft_trans_set(trans)->list);
|
|
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
|
|
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
|
|
NFT_MSG_DELSET, GFP_KERNEL);
|
|
NFT_MSG_DELSET, GFP_KERNEL);
|
|
break;
|
|
break;
|
|
@@ -4076,7 +4083,8 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
case NFT_MSG_NEWTABLE:
|
|
case NFT_MSG_NEWTABLE:
|
|
if (nft_trans_table_update(trans)) {
|
|
if (nft_trans_table_update(trans)) {
|
|
if (nft_trans_table_enable(trans)) {
|
|
if (nft_trans_table_enable(trans)) {
|
|
- nf_tables_table_disable(trans->ctx.afi,
|
|
|
|
|
|
+ nf_tables_table_disable(net,
|
|
|
|
+ trans->ctx.afi,
|
|
trans->ctx.table);
|
|
trans->ctx.table);
|
|
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
|
trans->ctx.table->flags |= NFT_TABLE_F_DORMANT;
|
|
}
|
|
}
|
|
@@ -4086,8 +4094,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELTABLE:
|
|
case NFT_MSG_DELTABLE:
|
|
- list_add_tail_rcu(&trans->ctx.table->list,
|
|
|
|
- &trans->ctx.afi->tables);
|
|
|
|
|
|
+ nft_clear(trans->ctx.net, trans->ctx.table);
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWCHAIN:
|
|
case NFT_MSG_NEWCHAIN:
|
|
@@ -4098,15 +4105,15 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
} else {
|
|
} else {
|
|
trans->ctx.table->use--;
|
|
trans->ctx.table->use--;
|
|
list_del_rcu(&trans->ctx.chain->list);
|
|
list_del_rcu(&trans->ctx.chain->list);
|
|
- nf_tables_unregister_hooks(trans->ctx.table,
|
|
|
|
|
|
+ nf_tables_unregister_hooks(trans->ctx.net,
|
|
|
|
+ trans->ctx.table,
|
|
trans->ctx.chain,
|
|
trans->ctx.chain,
|
|
trans->ctx.afi->nops);
|
|
trans->ctx.afi->nops);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELCHAIN:
|
|
case NFT_MSG_DELCHAIN:
|
|
trans->ctx.table->use++;
|
|
trans->ctx.table->use++;
|
|
- list_add_tail_rcu(&trans->ctx.chain->list,
|
|
|
|
- &trans->ctx.table->chains);
|
|
|
|
|
|
+ nft_clear(trans->ctx.net, trans->ctx.chain);
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWRULE:
|
|
case NFT_MSG_NEWRULE:
|
|
@@ -4115,7 +4122,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELRULE:
|
|
case NFT_MSG_DELRULE:
|
|
trans->ctx.chain->use++;
|
|
trans->ctx.chain->use++;
|
|
- nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
|
|
|
|
+ nft_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWSET:
|
|
case NFT_MSG_NEWSET:
|
|
@@ -4124,8 +4131,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
break;
|
|
break;
|
|
case NFT_MSG_DELSET:
|
|
case NFT_MSG_DELSET:
|
|
trans->ctx.table->use++;
|
|
trans->ctx.table->use++;
|
|
- list_add_tail_rcu(&nft_trans_set(trans)->list,
|
|
|
|
- &trans->ctx.table->sets);
|
|
|
|
|
|
+ nft_clear(trans->ctx.net, nft_trans_set(trans));
|
|
nft_trans_destroy(trans);
|
|
nft_trans_destroy(trans);
|
|
break;
|
|
break;
|
|
case NFT_MSG_NEWSETELEM:
|
|
case NFT_MSG_NEWSETELEM:
|
|
@@ -4272,6 +4278,8 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
|
|
}
|
|
}
|
|
|
|
|
|
list_for_each_entry(set, &ctx->table->sets, list) {
|
|
list_for_each_entry(set, &ctx->table->sets, list) {
|
|
|
|
+ if (!nft_is_active_next(ctx->net, set))
|
|
|
|
+ continue;
|
|
if (!(set->flags & NFT_SET_MAP) ||
|
|
if (!(set->flags & NFT_SET_MAP) ||
|
|
set->dtype != NFT_DATA_VERDICT)
|
|
set->dtype != NFT_DATA_VERDICT)
|
|
continue;
|
|
continue;
|
|
@@ -4430,6 +4438,7 @@ static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
|
|
static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
struct nft_data_desc *desc, const struct nlattr *nla)
|
|
struct nft_data_desc *desc, const struct nlattr *nla)
|
|
{
|
|
{
|
|
|
|
+ u8 genmask = nft_genmask_next(ctx->net);
|
|
struct nlattr *tb[NFTA_VERDICT_MAX + 1];
|
|
struct nlattr *tb[NFTA_VERDICT_MAX + 1];
|
|
struct nft_chain *chain;
|
|
struct nft_chain *chain;
|
|
int err;
|
|
int err;
|
|
@@ -4462,7 +4471,7 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
|
|
if (!tb[NFTA_VERDICT_CHAIN])
|
|
if (!tb[NFTA_VERDICT_CHAIN])
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
chain = nf_tables_chain_lookup(ctx->table,
|
|
chain = nf_tables_chain_lookup(ctx->table,
|
|
- tb[NFTA_VERDICT_CHAIN]);
|
|
|
|
|
|
+ tb[NFTA_VERDICT_CHAIN], genmask);
|
|
if (IS_ERR(chain))
|
|
if (IS_ERR(chain))
|
|
return PTR_ERR(chain);
|
|
return PTR_ERR(chain);
|
|
if (chain->flags & NFT_BASE_CHAIN)
|
|
if (chain->flags & NFT_BASE_CHAIN)
|
|
@@ -4640,7 +4649,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
|
|
|
|
|
|
BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN));
|
|
BUG_ON(!(ctx->chain->flags & NFT_BASE_CHAIN));
|
|
|
|
|
|
- nf_tables_unregister_hooks(ctx->chain->table, ctx->chain,
|
|
|
|
|
|
+ nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain,
|
|
ctx->afi->nops);
|
|
ctx->afi->nops);
|
|
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
|
|
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
|
|
list_del(&rule->list);
|
|
list_del(&rule->list);
|
|
@@ -4669,7 +4678,8 @@ static void __nft_release_afinfo(struct net *net, struct nft_af_info *afi)
|
|
|
|
|
|
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
|
list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
|
list_for_each_entry(chain, &table->chains, list)
|
|
list_for_each_entry(chain, &table->chains, list)
|
|
- nf_tables_unregister_hooks(table, chain, afi->nops);
|
|
|
|
|
|
+ nf_tables_unregister_hooks(net, table, chain,
|
|
|
|
+ afi->nops);
|
|
/* No packets are walking on these chains anymore. */
|
|
/* No packets are walking on these chains anymore. */
|
|
ctx.table = table;
|
|
ctx.table = table;
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
list_for_each_entry(chain, &table->chains, list) {
|