summaryrefslogtreecommitdiffstats
path: root/src/optimize.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2022-06-17 17:49:59 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2022-06-23 19:00:02 +0200
commit887405df6b654cbd7a480d36db10eb98f9bb19fa (patch)
treea548e754c644d4b9a11ceb91fd14273dc56ecc9c /src/optimize.c
parent8f61a69e035d04834937fc28a42cf1841d825054 (diff)
optimize: add unsupported statement
Do not try to merge rules with unsupported statements. This patch adds a dummy unsupported statement which is included in the statement collection and the rule vs statement matrix. When looking for possible rule mergers, rules using unsupported statements are discarded, otherwise bogus rule mergers might occur. Note that __stmt_type_eq() already returns false for unsupported statements. Add a test using meta mark statement, which is not yet supported. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/optimize.c')
-rw-r--r--src/optimize.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/src/optimize.c b/src/optimize.c
index abd0b72f..e3d4bc78 100644
--- a/src/optimize.c
+++ b/src/optimize.c
@@ -301,16 +301,42 @@ static bool stmt_verdict_eq(const struct stmt *stmt_a, const struct stmt *stmt_b
static bool stmt_type_find(struct optimize_ctx *ctx, const struct stmt *stmt)
{
+ bool unsupported_exists = false;
uint32_t i;
for (i = 0; i < ctx->num_stmts; i++) {
+ if (ctx->stmt[i]->ops->type == STMT_INVALID)
+ unsupported_exists = true;
+
if (__stmt_type_eq(stmt, ctx->stmt[i], false))
return true;
}
+ switch (stmt->ops->type) {
+ case STMT_EXPRESSION:
+ case STMT_VERDICT:
+ case STMT_COUNTER:
+ case STMT_NOTRACK:
+ case STMT_LIMIT:
+ case STMT_LOG:
+ case STMT_NAT:
+ case STMT_REJECT:
+ break;
+ default:
+ /* add unsupported statement only once to statement matrix. */
+ if (unsupported_exists)
+ return true;
+ break;
+ }
+
return false;
}
+static struct stmt_ops unsupported_stmt_ops = {
+ .type = STMT_INVALID,
+ .name = "unsupported",
+};
+
static int rule_collect_stmts(struct optimize_ctx *ctx, struct rule *rule)
{
struct stmt *stmt, *clone;
@@ -357,8 +383,8 @@ static int rule_collect_stmts(struct optimize_ctx *ctx, struct rule *rule)
clone->reject.family = stmt->reject.family;
break;
default:
- xfree(clone);
- continue;
+ clone->ops = &unsupported_stmt_ops;
+ break;
}
ctx->stmt[ctx->num_stmts++] = clone;
@@ -369,6 +395,18 @@ static int rule_collect_stmts(struct optimize_ctx *ctx, struct rule *rule)
return 0;
}
+static int unsupported_in_stmt_matrix(const struct optimize_ctx *ctx)
+{
+ uint32_t i;
+
+ for (i = 0; i < ctx->num_stmts; i++) {
+ if (ctx->stmt[i]->ops->type == STMT_INVALID)
+ return i;
+ }
+ /* this should not happen. */
+ return -1;
+}
+
static int cmd_stmt_find_in_stmt_matrix(struct optimize_ctx *ctx, struct stmt *stmt)
{
uint32_t i;
@@ -377,10 +415,14 @@ static int cmd_stmt_find_in_stmt_matrix(struct optimize_ctx *ctx, struct stmt *s
if (__stmt_type_eq(stmt, ctx->stmt[i], false))
return i;
}
- /* should not ever happen. */
- return 0;
+
+ return -1;
}
+static struct stmt unsupported_stmt = {
+ .ops = &unsupported_stmt_ops,
+};
+
static void rule_build_stmt_matrix_stmts(struct optimize_ctx *ctx,
struct rule *rule, uint32_t *i)
{
@@ -389,6 +431,12 @@ static void rule_build_stmt_matrix_stmts(struct optimize_ctx *ctx,
list_for_each_entry(stmt, &rule->stmts, list) {
k = cmd_stmt_find_in_stmt_matrix(ctx, stmt);
+ if (k < 0) {
+ k = unsupported_in_stmt_matrix(ctx);
+ assert(k >= 0);
+ ctx->stmt_matrix[*i][k] = &unsupported_stmt;
+ continue;
+ }
ctx->stmt_matrix[*i][k] = stmt;
}
ctx->rule[(*i)++] = rule;