summaryrefslogtreecommitdiffstats
path: root/src/payload.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2018-02-14 16:26:50 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-02-15 16:29:32 +0100
commit477a2d86c54ee8e1a8426838439e9960f892ac29 (patch)
treee1b176707b5bb5c82ce50474c5db292ec52c7d89 /src/payload.c
parenta5112cc040f81806ab76d5fa0a34a2cc34da9b84 (diff)
src: add payload_dependency_exists()
This helper function tells us if there is already a protocol key payload expression, ie. those with EXPR_F_PROTOCOL flag set on, that we might want to remove since we can infer from another expression in the upper protocol base, eg. ip protocol tcp tcp dport 22 'ip protocol tcp' can be removed in the ip family since it is redundant, but not in the netdev, bridge and inet families, where we cannot make assumptions on the layer 3 protocol. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/payload.c')
-rw-r--r--src/payload.c34
1 files changed, 25 insertions, 9 deletions
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;