|
@@ -127,6 +127,204 @@ static void nft_trans_destroy(struct nft_trans *trans)
|
|
|
kfree(trans);
|
|
|
}
|
|
|
|
|
|
+static void nf_tables_unregister_hooks(const struct nft_table *table,
|
|
|
+ const struct nft_chain *chain,
|
|
|
+ unsigned int hook_nops)
|
|
|
+{
|
|
|
+ if (!(table->flags & NFT_TABLE_F_DORMANT) &&
|
|
|
+ chain->flags & NFT_BASE_CHAIN)
|
|
|
+ nf_unregister_hooks(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)
|
|
|
+{
|
|
|
+ struct nft_trans *trans;
|
|
|
+
|
|
|
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table));
|
|
|
+ if (trans == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (msg_type == NFT_MSG_NEWTABLE)
|
|
|
+ ctx->table->flags |= NFT_TABLE_INACTIVE;
|
|
|
+
|
|
|
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_deltable(struct nft_ctx *ctx)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nft_trans_table_add(ctx, NFT_MSG_DELTABLE);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ list_del_rcu(&ctx->table->list);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
|
|
|
+{
|
|
|
+ struct nft_trans *trans;
|
|
|
+
|
|
|
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
|
|
|
+ if (trans == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (msg_type == NFT_MSG_NEWCHAIN)
|
|
|
+ ctx->chain->flags |= NFT_CHAIN_INACTIVE;
|
|
|
+
|
|
|
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_delchain(struct nft_ctx *ctx)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ ctx->table->use--;
|
|
|
+ list_del_rcu(&ctx->chain->list);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static inline bool
|
|
|
+nft_rule_is_active(struct net *net, const struct nft_rule *rule)
|
|
|
+{
|
|
|
+ return (rule->genmask & (1 << net->nft.gencursor)) == 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int gencursor_next(struct net *net)
|
|
|
+{
|
|
|
+ return net->nft.gencursor+1 == 1 ? 1 : 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int
|
|
|
+nft_rule_is_active_next(struct net *net, const struct nft_rule *rule)
|
|
|
+{
|
|
|
+ return (rule->genmask & (1 << gencursor_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 = (1 << net->nft.gencursor);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void
|
|
|
+nft_rule_deactivate_next(struct net *net, struct nft_rule *rule)
|
|
|
+{
|
|
|
+ rule->genmask = (1 << gencursor_next(net));
|
|
|
+}
|
|
|
+
|
|
|
+static inline void nft_rule_clear(struct net *net, struct nft_rule *rule)
|
|
|
+{
|
|
|
+ rule->genmask = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
+{
|
|
|
+ /* You cannot delete the same rule twice */
|
|
|
+ if (nft_rule_is_active_next(ctx->net, rule)) {
|
|
|
+ nft_rule_deactivate_next(ctx->net, rule);
|
|
|
+ ctx->chain->use--;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return -ENOENT;
|
|
|
+}
|
|
|
+
|
|
|
+static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
|
|
|
+ struct nft_rule *rule)
|
|
|
+{
|
|
|
+ struct nft_trans *trans;
|
|
|
+
|
|
|
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
|
|
|
+ if (trans == NULL)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ nft_trans_rule(trans) = rule;
|
|
|
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
+
|
|
|
+ return trans;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
+{
|
|
|
+ struct nft_trans *trans;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ trans = nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule);
|
|
|
+ if (trans == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ err = nf_tables_delrule_deactivate(ctx, rule);
|
|
|
+ if (err < 0) {
|
|
|
+ nft_trans_destroy(trans);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_delrule_by_chain(struct nft_ctx *ctx)
|
|
|
+{
|
|
|
+ struct nft_rule *rule;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ list_for_each_entry(rule, &ctx->chain->rules, list) {
|
|
|
+ err = nft_delrule(ctx, rule);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* Internal set flag */
|
|
|
+#define NFT_SET_INACTIVE (1 << 15)
|
|
|
+
|
|
|
+static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
|
|
|
+ struct nft_set *set)
|
|
|
+{
|
|
|
+ struct nft_trans *trans;
|
|
|
+
|
|
|
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set));
|
|
|
+ if (trans == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
|
|
|
+ nft_trans_set_id(trans) =
|
|
|
+ ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
|
|
|
+ set->flags |= NFT_SET_INACTIVE;
|
|
|
+ }
|
|
|
+ nft_trans_set(trans) = set;
|
|
|
+ list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = nft_trans_set_add(ctx, NFT_MSG_DELSET, set);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ list_del_rcu(&set->list);
|
|
|
+ ctx->table->use--;
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Tables
|
|
|
*/
|
|
@@ -309,9 +507,6 @@ done:
|
|
|
return skb->len;
|
|
|
}
|
|
|
|
|
|
-/* Internal table flags */
|
|
|
-#define NFT_TABLE_INACTIVE (1 << 15)
|
|
|
-
|
|
|
static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -443,21 +638,6 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
|
|
|
-{
|
|
|
- struct nft_trans *trans;
|
|
|
-
|
|
|
- trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table));
|
|
|
- if (trans == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (msg_type == NFT_MSG_NEWTABLE)
|
|
|
- ctx->table->flags |= NFT_TABLE_INACTIVE;
|
|
|
-
|
|
|
- list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -527,6 +707,67 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int nft_flush_table(struct nft_ctx *ctx)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+ struct nft_chain *chain, *nc;
|
|
|
+ struct nft_set *set, *ns;
|
|
|
+
|
|
|
+ list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
|
|
|
+ ctx->chain = chain;
|
|
|
+
|
|
|
+ err = nft_delrule_by_chain(ctx);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ err = nft_delchain(ctx);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
|
|
|
+ if (set->flags & NFT_SET_ANONYMOUS &&
|
|
|
+ !list_empty(&set->bindings))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ err = nft_delset(ctx, set);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = nft_deltable(ctx);
|
|
|
+out:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int nft_flush(struct nft_ctx *ctx, int family)
|
|
|
+{
|
|
|
+ struct nft_af_info *afi;
|
|
|
+ struct nft_table *table, *nt;
|
|
|
+ const struct nlattr * const *nla = ctx->nla;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ list_for_each_entry(afi, &ctx->net->nft.af_info, list) {
|
|
|
+ if (family != AF_UNSPEC && afi->family != family)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ctx->afi = afi;
|
|
|
+ list_for_each_entry_safe(table, nt, &afi->tables, list) {
|
|
|
+ if (nla[NFTA_TABLE_NAME] &&
|
|
|
+ nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ctx->table = table;
|
|
|
+
|
|
|
+ err = nft_flush_table(ctx);
|
|
|
+ if (err < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+out:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -535,9 +776,13 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
struct nft_af_info *afi;
|
|
|
struct nft_table *table;
|
|
|
struct net *net = sock_net(skb->sk);
|
|
|
- int family = nfmsg->nfgen_family, err;
|
|
|
+ int family = nfmsg->nfgen_family;
|
|
|
struct nft_ctx ctx;
|
|
|
|
|
|
+ nft_ctx_init(&ctx, skb, nlh, NULL, NULL, NULL, nla);
|
|
|
+ if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL)
|
|
|
+ return nft_flush(&ctx, family);
|
|
|
+
|
|
|
afi = nf_tables_afinfo_lookup(net, family, false);
|
|
|
if (IS_ERR(afi))
|
|
|
return PTR_ERR(afi);
|
|
@@ -547,16 +792,11 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
|
|
|
return PTR_ERR(table);
|
|
|
if (table->flags & NFT_TABLE_INACTIVE)
|
|
|
return -ENOENT;
|
|
|
- if (table->use > 0)
|
|
|
- return -EBUSY;
|
|
|
|
|
|
- nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
|
|
|
- err = nft_trans_table_add(&ctx, NFT_MSG_DELTABLE);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
+ ctx.afi = afi;
|
|
|
+ ctx.table = table;
|
|
|
|
|
|
- list_del_rcu(&table->list);
|
|
|
- return 0;
|
|
|
+ return nft_flush_table(&ctx);
|
|
|
}
|
|
|
|
|
|
static void nf_tables_table_destroy(struct nft_ctx *ctx)
|
|
@@ -913,21 +1153,6 @@ static void nft_chain_stats_replace(struct nft_base_chain *chain,
|
|
|
rcu_assign_pointer(chain->stats, newstats);
|
|
|
}
|
|
|
|
|
|
-static int nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
|
|
|
-{
|
|
|
- struct nft_trans *trans;
|
|
|
-
|
|
|
- trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
|
|
|
- if (trans == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (msg_type == NFT_MSG_NEWCHAIN)
|
|
|
- ctx->chain->flags |= NFT_CHAIN_INACTIVE;
|
|
|
-
|
|
|
- list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void nf_tables_chain_destroy(struct nft_chain *chain)
|
|
|
{
|
|
|
BUG_ON(chain->use > 0);
|
|
@@ -1157,11 +1382,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
|
|
|
list_add_tail_rcu(&chain->list, &table->chains);
|
|
|
return 0;
|
|
|
err2:
|
|
|
- if (!(table->flags & NFT_TABLE_F_DORMANT) &&
|
|
|
- chain->flags & NFT_BASE_CHAIN) {
|
|
|
- nf_unregister_hooks(nft_base_chain(chain)->ops,
|
|
|
- afi->nops);
|
|
|
- }
|
|
|
+ nf_tables_unregister_hooks(table, chain, afi->nops);
|
|
|
err1:
|
|
|
nf_tables_chain_destroy(chain);
|
|
|
return err;
|
|
@@ -1178,7 +1399,6 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
|
|
|
struct net *net = sock_net(skb->sk);
|
|
|
int family = nfmsg->nfgen_family;
|
|
|
struct nft_ctx ctx;
|
|
|
- int err;
|
|
|
|
|
|
afi = nf_tables_afinfo_lookup(net, family, false);
|
|
|
if (IS_ERR(afi))
|
|
@@ -1199,13 +1419,8 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
|
|
|
return -EBUSY;
|
|
|
|
|
|
nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
|
|
|
- err = nft_trans_chain_add(&ctx, NFT_MSG_DELCHAIN);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
|
|
|
- table->use--;
|
|
|
- list_del_rcu(&chain->list);
|
|
|
- return 0;
|
|
|
+ return nft_delchain(&ctx);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -1527,41 +1742,6 @@ err:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static inline bool
|
|
|
-nft_rule_is_active(struct net *net, const struct nft_rule *rule)
|
|
|
-{
|
|
|
- return (rule->genmask & (1 << net->nft.gencursor)) == 0;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int gencursor_next(struct net *net)
|
|
|
-{
|
|
|
- return net->nft.gencursor+1 == 1 ? 1 : 0;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int
|
|
|
-nft_rule_is_active_next(struct net *net, const struct nft_rule *rule)
|
|
|
-{
|
|
|
- return (rule->genmask & (1 << gencursor_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 = (1 << net->nft.gencursor);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void
|
|
|
-nft_rule_disactivate_next(struct net *net, struct nft_rule *rule)
|
|
|
-{
|
|
|
- rule->genmask = (1 << gencursor_next(net));
|
|
|
-}
|
|
|
-
|
|
|
-static inline void nft_rule_clear(struct net *net, struct nft_rule *rule)
|
|
|
-{
|
|
|
- rule->genmask = 0;
|
|
|
-}
|
|
|
-
|
|
|
static int nf_tables_dump_rules(struct sk_buff *skb,
|
|
|
struct netlink_callback *cb)
|
|
|
{
|
|
@@ -1687,21 +1867,6 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
|
|
kfree(rule);
|
|
|
}
|
|
|
|
|
|
-static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
|
|
|
- struct nft_rule *rule)
|
|
|
-{
|
|
|
- struct nft_trans *trans;
|
|
|
-
|
|
|
- trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
|
|
|
- if (trans == NULL)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- nft_trans_rule(trans) = rule;
|
|
|
- list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
-
|
|
|
- return trans;
|
|
|
-}
|
|
|
-
|
|
|
#define NFT_RULE_MAXEXPRS 128
|
|
|
|
|
|
static struct nft_expr_info *info;
|
|
@@ -1823,7 +1988,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
|
|
|
err = -ENOMEM;
|
|
|
goto err2;
|
|
|
}
|
|
|
- nft_rule_disactivate_next(net, old_rule);
|
|
|
+ nft_rule_deactivate_next(net, old_rule);
|
|
|
chain->use--;
|
|
|
list_add_tail_rcu(&rule->list, &old_rule->list);
|
|
|
} else {
|
|
@@ -1867,33 +2032,6 @@ err1:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
-{
|
|
|
- /* You cannot delete the same rule twice */
|
|
|
- if (nft_rule_is_active_next(ctx->net, rule)) {
|
|
|
- if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL)
|
|
|
- return -ENOMEM;
|
|
|
- nft_rule_disactivate_next(ctx->net, rule);
|
|
|
- ctx->chain->use--;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return -ENOENT;
|
|
|
-}
|
|
|
-
|
|
|
-static int nf_table_delrule_by_chain(struct nft_ctx *ctx)
|
|
|
-{
|
|
|
- struct nft_rule *rule;
|
|
|
- int err;
|
|
|
-
|
|
|
- list_for_each_entry(rule, &ctx->chain->rules, list) {
|
|
|
- err = nf_tables_delrule_one(ctx, rule);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -1932,14 +2070,14 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
|
|
|
if (IS_ERR(rule))
|
|
|
return PTR_ERR(rule);
|
|
|
|
|
|
- err = nf_tables_delrule_one(&ctx, rule);
|
|
|
+ err = nft_delrule(&ctx, rule);
|
|
|
} else {
|
|
|
- err = nf_table_delrule_by_chain(&ctx);
|
|
|
+ err = nft_delrule_by_chain(&ctx);
|
|
|
}
|
|
|
} else {
|
|
|
list_for_each_entry(chain, &table->chains, list) {
|
|
|
ctx.chain = chain;
|
|
|
- err = nf_table_delrule_by_chain(&ctx);
|
|
|
+ err = nft_delrule_by_chain(&ctx);
|
|
|
if (err < 0)
|
|
|
break;
|
|
|
}
|
|
@@ -2322,8 +2460,6 @@ static int nf_tables_dump_sets_done(struct netlink_callback *cb)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */
|
|
|
-
|
|
|
static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -2398,26 +2534,6 @@ static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
|
|
|
- struct nft_set *set)
|
|
|
-{
|
|
|
- struct nft_trans *trans;
|
|
|
-
|
|
|
- trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set));
|
|
|
- if (trans == NULL)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
|
|
|
- nft_trans_set_id(trans) =
|
|
|
- ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
|
|
|
- set->flags |= NFT_SET_INACTIVE;
|
|
|
- }
|
|
|
- nft_trans_set(trans) = set;
|
|
|
- list_add_tail(&trans->list, &ctx->net->nft.commit_list);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
|
|
|
const struct nlmsghdr *nlh,
|
|
|
const struct nlattr * const nla[])
|
|
@@ -2611,13 +2727,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
|
|
|
if (!list_empty(&set->bindings))
|
|
|
return -EBUSY;
|
|
|
|
|
|
- err = nft_trans_set_add(&ctx, NFT_MSG_DELSET, set);
|
|
|
- if (err < 0)
|
|
|
- return err;
|
|
|
-
|
|
|
- list_del_rcu(&set->list);
|
|
|
- ctx.table->use--;
|
|
|
- return 0;
|
|
|
+ return nft_delset(&ctx, set);
|
|
|
}
|
|
|
|
|
|
static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
|
|
@@ -3352,11 +3462,9 @@ static int nf_tables_commit(struct sk_buff *skb)
|
|
|
break;
|
|
|
case NFT_MSG_DELCHAIN:
|
|
|
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
|
|
|
- if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
|
|
|
- trans->ctx.chain->flags & NFT_BASE_CHAIN) {
|
|
|
- nf_unregister_hooks(nft_base_chain(trans->ctx.chain)->ops,
|
|
|
- trans->ctx.afi->nops);
|
|
|
- }
|
|
|
+ nf_tables_unregister_hooks(trans->ctx.table,
|
|
|
+ trans->ctx.chain,
|
|
|
+ trans->ctx.afi->nops);
|
|
|
break;
|
|
|
case NFT_MSG_NEWRULE:
|
|
|
nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
@@ -3479,11 +3587,9 @@ static int nf_tables_abort(struct sk_buff *skb)
|
|
|
} else {
|
|
|
trans->ctx.table->use--;
|
|
|
list_del_rcu(&trans->ctx.chain->list);
|
|
|
- if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT) &&
|
|
|
- trans->ctx.chain->flags & NFT_BASE_CHAIN) {
|
|
|
- nf_unregister_hooks(nft_base_chain(trans->ctx.chain)->ops,
|
|
|
- trans->ctx.afi->nops);
|
|
|
- }
|
|
|
+ nf_tables_unregister_hooks(trans->ctx.table,
|
|
|
+ trans->ctx.chain,
|
|
|
+ trans->ctx.afi->nops);
|
|
|
}
|
|
|
break;
|
|
|
case NFT_MSG_DELCHAIN:
|