|
@@ -214,6 +214,34 @@ static int nft_delchain(struct nft_ctx *ctx)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static void nft_rule_expr_activate(const struct nft_ctx *ctx,
|
|
|
+ struct nft_rule *rule)
|
|
|
+{
|
|
|
+ struct nft_expr *expr;
|
|
|
+
|
|
|
+ expr = nft_expr_first(rule);
|
|
|
+ while (expr != nft_expr_last(rule) && expr->ops) {
|
|
|
+ if (expr->ops->activate)
|
|
|
+ expr->ops->activate(ctx, expr);
|
|
|
+
|
|
|
+ expr = nft_expr_next(expr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
|
|
|
+ struct nft_rule *rule)
|
|
|
+{
|
|
|
+ struct nft_expr *expr;
|
|
|
+
|
|
|
+ expr = nft_expr_first(rule);
|
|
|
+ while (expr != nft_expr_last(rule) && expr->ops) {
|
|
|
+ if (expr->ops->deactivate)
|
|
|
+ expr->ops->deactivate(ctx, expr);
|
|
|
+
|
|
|
+ expr = nft_expr_next(expr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
{
|
|
@@ -259,6 +287,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
|
|
|
nft_trans_destroy(trans);
|
|
|
return err;
|
|
|
}
|
|
|
+ nft_rule_expr_deactivate(ctx, rule);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -2238,6 +2267,13 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
|
|
|
kfree(rule);
|
|
|
}
|
|
|
|
|
|
+static void nf_tables_rule_release(const struct nft_ctx *ctx,
|
|
|
+ struct nft_rule *rule)
|
|
|
+{
|
|
|
+ nft_rule_expr_deactivate(ctx, rule);
|
|
|
+ nf_tables_rule_destroy(ctx, rule);
|
|
|
+}
|
|
|
+
|
|
|
#define NFT_RULE_MAXEXPRS 128
|
|
|
|
|
|
static struct nft_expr_info *info;
|
|
@@ -2402,7 +2438,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
|
|
|
return 0;
|
|
|
|
|
|
err2:
|
|
|
- nf_tables_rule_destroy(&ctx, rule);
|
|
|
+ nf_tables_rule_release(&ctx, rule);
|
|
|
err1:
|
|
|
for (i = 0; i < n; i++) {
|
|
|
if (info[i].ops != NULL)
|
|
@@ -4130,7 +4166,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
|
|
|
* NFT_GOTO verdicts. This function must be called on active data objects
|
|
|
* from the second phase of the commit protocol.
|
|
|
*/
|
|
|
-static void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
|
|
+void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
|
|
|
{
|
|
|
if (type == NFT_DATA_VERDICT) {
|
|
|
switch (data->verdict.code) {
|
|
@@ -6015,10 +6051,12 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
|
|
|
case NFT_MSG_NEWRULE:
|
|
|
trans->ctx.chain->use--;
|
|
|
list_del_rcu(&nft_trans_rule(trans)->list);
|
|
|
+ nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
|
|
|
break;
|
|
|
case NFT_MSG_DELRULE:
|
|
|
trans->ctx.chain->use++;
|
|
|
nft_clear(trans->ctx.net, nft_trans_rule(trans));
|
|
|
+ nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
|
|
|
nft_trans_destroy(trans);
|
|
|
break;
|
|
|
case NFT_MSG_NEWSET:
|
|
@@ -6594,7 +6632,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
|
|
|
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
|
|
|
list_del(&rule->list);
|
|
|
ctx->chain->use--;
|
|
|
- nf_tables_rule_destroy(ctx, rule);
|
|
|
+ nf_tables_rule_release(ctx, rule);
|
|
|
}
|
|
|
list_del(&ctx->chain->list);
|
|
|
ctx->table->use--;
|
|
@@ -6632,7 +6670,7 @@ static void __nft_release_tables(struct net *net)
|
|
|
list_for_each_entry_safe(rule, nr, &chain->rules, list) {
|
|
|
list_del(&rule->list);
|
|
|
chain->use--;
|
|
|
- nf_tables_rule_destroy(&ctx, rule);
|
|
|
+ nf_tables_rule_release(&ctx, rule);
|
|
|
}
|
|
|
}
|
|
|
list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
|