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

index 294ff2706e30309bfa6a414f78010be76e4f1c97..dec4647aad9fa852e97f0de4ab88397fa195b6c4 100644 (file)
@@ -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);
index 8d11969e0fb1103ea6d3dc700b4cfb97ccd9fdc4..f4b943964fc9559aaecf1a2976a58274374c653b 100644 (file)
@@ -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:
index 21c2842807cd04bbb84fa3f4cd3ca66869939a22..df59ac8adcace90f33b1a0c914cb81c9ef32de20 100644 (file)
@@ -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;