]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
payload: add payload_may_dependency_kill()
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 14 Feb 2018 15:27:01 +0000 (16:27 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 15 Feb 2018 15:29:32 +0000 (16:29 +0100)
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>
src/payload.c

index 383aed039a5e042bc3bcde5335fc9694618b5bda..15d055b6be7e42241adf9e368662090a9e8162a0 100644 (file)
@@ -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);
 }