extern bool payload_is_known(const struct expr *expr);
extern bool payload_is_stacked(const struct proto_desc *desc,
const struct expr *expr);
+
+void payload_dependency_reset(struct payload_dep_ctx *ctx);
extern void payload_dependency_store(struct payload_dep_ctx *ctx,
struct stmt *stmt,
enum proto_bases base);
expr_postprocess(ctx, &stmt->payload.val);
}
+/*
+ * We can only remove payload dependencies if they occur without
+ * a statment with side effects in between.
+ *
+ * For instance:
+ * 'ip protocol tcp tcp dport 22 counter' is same as
+ * 'tcp dport 22 counter'.
+ *
+ * 'ip protocol tcp counter tcp dport 22' cannot be written as
+ * 'counter tcp dport 22' (that would be counter ip protocol tcp, but
+ * that counts every packet, not just ip/tcp).
+ */
+static void
+rule_maybe_reset_payload_deps(struct payload_dep_ctx *pdctx, enum stmt_types t)
+{
+ if (t == STMT_EXPRESSION)
+ return;
+
+ payload_dependency_reset(pdctx);
+}
+
static void rule_parse_postprocess(struct netlink_parse_ctx *ctx, struct rule *rule)
{
struct rule_pp_ctx rctx;
proto_ctx_init(&rctx.pctx, rule->handle.family);
list_for_each_entry_safe(stmt, next, &rule->stmts, list) {
+ enum stmt_types type = stmt->ops->type;
+
rctx.stmt = stmt;
- switch (stmt->ops->type) {
+ switch (type) {
case STMT_EXPRESSION:
stmt_expr_postprocess(&rctx);
break;
default:
break;
}
+
rctx.pdctx.prev = rctx.stmt;
+
+ rule_maybe_reset_payload_deps(&rctx.pdctx, type);
}
}
return next && next->base == desc->base;
}
+void payload_dependency_reset(struct payload_dep_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+
/**
* payload_dependency_store - store a possibly redundant protocol match
*