summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2018-02-14 16:27:01 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-02-15 16:29:32 +0100
commita1bcf8a349754673a8deb69cbfbf631c4340f512 (patch)
treef9f402f935b43a708a3584e37770b5d56731c5e1 /src
parent7ac052cc2aae1af37192958e86755f7b5508760f (diff)
payload: add payload_may_dependency_kill()
Payload protocol key expressions at network base are meaningful in the netdev, bridge and inet families, do not exercise the redundant dependency removal in those cases since it breaks rule semantics. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/payload.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/payload.c b/src/payload.c
index 383aed03..15d055b6 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -456,6 +456,31 @@ void payload_dependency_release(struct payload_dep_ctx *ctx)
ctx->pdep = NULL;
}
+static bool payload_may_dependency_kill(struct payload_dep_ctx *ctx,
+ unsigned int family, struct expr *expr)
+{
+ struct expr *dep = ctx->pdep->expr;
+
+ /* Protocol key payload expression at network base such as 'ip6 nexthdr'
+ * need to be left in place since it implicitly restricts matching to
+ * IPv6 for the bridge, inet and netdev families.
+ */
+ switch (family) {
+ case NFPROTO_BRIDGE:
+ case NFPROTO_NETDEV:
+ case NFPROTO_INET:
+ if (dep->left->ops->type == EXPR_PAYLOAD &&
+ dep->left->payload.base == PROTO_BASE_NETWORK_HDR &&
+ (dep->left->payload.desc == &proto_ip ||
+ dep->left->payload.desc == &proto_ip6) &&
+ expr->payload.base == PROTO_BASE_TRANSPORT_HDR)
+ return false;
+ break;
+ }
+
+ return true;
+}
+
/**
* payload_dependency_kill - kill a redundant payload depedency
*
@@ -463,12 +488,14 @@ void payload_dependency_release(struct payload_dep_ctx *ctx)
* @expr: higher layer payload expression
*
* Kill a redundant payload expression if a higher layer payload expression
- * implies its existance.
+ * implies its existance. Skip this if the dependency is a network payload and
+ * we are in bridge, netdev and inet families.
*/
void payload_dependency_kill(struct payload_dep_ctx *ctx, struct expr *expr,
unsigned int family)
{
- if (payload_dependency_exists(ctx, expr->payload.base))
+ if (payload_dependency_exists(ctx, expr->payload.base) &&
+ payload_may_dependency_kill(ctx, family, expr))
payload_dependency_release(ctx);
}