summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/payload.h3
-rw-r--r--src/netlink_delinearize.c15
-rw-r--r--src/payload.c34
3 files changed, 36 insertions, 16 deletions
diff --git a/include/payload.h b/include/payload.h
index 294ff270..dec4647a 100644
--- a/include/payload.h
+++ b/include/payload.h
@@ -40,8 +40,9 @@ 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);
+extern bool payload_dependency_exists(const struct payload_dep_ctx *ctx,
+ enum proto_bases base);
extern void __payload_dependency_kill(struct payload_dep_ctx *ctx,
- enum proto_bases base,
unsigned int family);
extern void payload_dependency_kill(struct payload_dep_ctx *ctx,
struct expr *expr, unsigned int family);
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index 8d11969e..f4b94396 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1407,8 +1407,9 @@ static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
left->flags & EXPR_F_PROTOCOL) {
payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
} else if (ctx->pdctx.pbase < PROTO_BASE_TRANSPORT_HDR) {
- __payload_dependency_kill(&ctx->pdctx, base,
- ctx->pctx.family);
+ if (payload_dependency_exists(&ctx->pdctx, base))
+ __payload_dependency_kill(&ctx->pdctx,
+ ctx->pctx.family);
if (left->flags & EXPR_F_PROTOCOL)
payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
}
@@ -1870,17 +1871,19 @@ static void stmt_reject_postprocess(struct rule_pp_ctx *rctx)
case NFPROTO_IPV4:
stmt->reject.family = rctx->pctx.family;
stmt->reject.expr->dtype = &icmp_code_type;
- if (stmt->reject.type == NFT_REJECT_TCP_RST)
+ if (stmt->reject.type == NFT_REJECT_TCP_RST &&
+ payload_dependency_exists(&rctx->pdctx,
+ PROTO_BASE_TRANSPORT_HDR))
__payload_dependency_kill(&rctx->pdctx,
- PROTO_BASE_TRANSPORT_HDR,
rctx->pctx.family);
break;
case NFPROTO_IPV6:
stmt->reject.family = rctx->pctx.family;
stmt->reject.expr->dtype = &icmpv6_code_type;
- if (stmt->reject.type == NFT_REJECT_TCP_RST)
+ if (stmt->reject.type == NFT_REJECT_TCP_RST &&
+ payload_dependency_exists(&rctx->pdctx,
+ PROTO_BASE_TRANSPORT_HDR))
__payload_dependency_kill(&rctx->pdctx,
- PROTO_BASE_TRANSPORT_HDR,
rctx->pctx.family);
break;
case NFPROTO_INET:
diff --git a/src/payload.c b/src/payload.c
index 21c28428..df59ac8a 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -428,6 +428,23 @@ void payload_dependency_store(struct payload_dep_ctx *ctx,
ctx->pdep = stmt;
}
+/**
+ * payload_dependency_exists - there is a payload dependency in place
+ * @ctx: payload dependency context
+ * @base: payload protocol base
+ *
+ * Check if we have seen a protocol key payload expression for this base, we can
+ * usually remove it if we can infer it from another payload expression in the
+ * upper base.
+ */
+bool payload_dependency_exists(const struct payload_dep_ctx *ctx,
+ enum proto_bases base)
+{
+ return ctx->pbase != PROTO_BASE_INVALID &&
+ ctx->pbase == base &&
+ ctx->pdep != NULL;
+}
+
static void payload_dependency_release(struct payload_dep_ctx *ctx)
{
list_del(&ctx->pdep->list);
@@ -448,19 +465,16 @@ static void payload_dependency_release(struct payload_dep_ctx *ctx)
* Kill a redundant payload expression if a higher layer payload expression
* implies its existance.
*/
-void __payload_dependency_kill(struct payload_dep_ctx *ctx,
- enum proto_bases base, unsigned int family)
+void __payload_dependency_kill(struct payload_dep_ctx *ctx, unsigned int family)
{
- if (ctx->pbase != PROTO_BASE_INVALID &&
- ctx->pbase == base &&
- ctx->pdep != NULL)
- payload_dependency_release(ctx);
+ payload_dependency_release(ctx);
}
void payload_dependency_kill(struct payload_dep_ctx *ctx, struct expr *expr,
unsigned int family)
{
- __payload_dependency_kill(ctx, expr->payload.base, family);
+ if (payload_dependency_exists(ctx, expr->payload.base))
+ __payload_dependency_kill(ctx, family);
}
void exthdr_dependency_kill(struct payload_dep_ctx *ctx, struct expr *expr,
@@ -468,10 +482,12 @@ void exthdr_dependency_kill(struct payload_dep_ctx *ctx, struct expr *expr,
{
switch (expr->exthdr.op) {
case NFT_EXTHDR_OP_TCPOPT:
- __payload_dependency_kill(ctx, PROTO_BASE_TRANSPORT_HDR, family);
+ if (payload_dependency_exists(ctx, PROTO_BASE_TRANSPORT_HDR))
+ __payload_dependency_kill(ctx, family);
break;
case NFT_EXTHDR_OP_IPV6:
- __payload_dependency_kill(ctx, PROTO_BASE_NETWORK_HDR, family);
+ if (payload_dependency_exists(ctx, PROTO_BASE_NETWORK_HDR))
+ __payload_dependency_kill(ctx, family);
break;
default:
break;