[PATCH nft 6/6] netlink_delinearize: add meta_may_dependency_kill()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Do not exercise dependency removal for protocol key network payload
expressions in bridge, netdev and inet families from meta expressions,
more specifically:

* inet: nfproto and ether type.
* netdev and bridge: meta protocol and ether type.

need to be left in place.

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 src/netlink_delinearize.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index b9f195b07d63..82eefa61d4a4 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -1389,6 +1389,74 @@ static void payload_match_postprocess(struct rule_pp_ctx *ctx,
 	}
 }
 
+/* We have seen a protocol key expression that restricts matching at the network
+ * base, leave it in place since this is meaninful in bridge, inet and netdev
+ * families. Exceptions are ICMP and ICMPv6 where this code assumes that can
+ * only happen with IPv4 and IPv6.
+ */
+static bool meta_may_dependency_kill(struct payload_dep_ctx *ctx,
+				     unsigned int family,
+				     const struct expr *expr)
+{
+	struct expr *dep = ctx->pdep->expr;
+
+	if (ctx->pbase != PROTO_BASE_NETWORK_HDR)
+		return true;
+
+	switch (family) {
+	case NFPROTO_INET:
+		switch (dep->left->ops->type) {
+		case EXPR_META:
+			if (dep->left->meta.key == NFT_META_NFPROTO &&
+			    (mpz_get_uint16(dep->right->value) == NFPROTO_IPV4 ||
+			     mpz_get_uint16(dep->right->value) == NFPROTO_IPV6) &&
+			    expr->left->meta.key == NFT_META_L4PROTO &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
+				return false;
+			break;
+		case EXPR_PAYLOAD:
+			if (dep->left->payload.base == PROTO_BASE_LL_HDR &&
+			    (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
+			     mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
+			    expr->left->meta.key == NFT_META_L4PROTO &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
+				return false;
+			break;
+		default:
+			break;
+		}
+		break;
+	case NFPROTO_NETDEV:
+	case NFPROTO_BRIDGE:
+		switch (dep->left->ops->type) {
+		case EXPR_META:
+			if (dep->left->meta.key == NFT_META_PROTOCOL &&
+			    (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
+			     mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
+			    expr->left->meta.key == NFT_META_L4PROTO &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
+				return false;
+			break;
+		case EXPR_PAYLOAD:
+			if (dep->left->payload.base == PROTO_BASE_LL_HDR &&
+			    (mpz_get_uint16(dep->right->value) == ETH_P_IP ||
+			     mpz_get_uint16(dep->right->value) == ETH_P_IPV6) &&
+			    expr->left->meta.key == NFT_META_L4PROTO &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMP &&
+			    mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6)
+				return false;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	return true;
+}
+
 static void ct_meta_common_postprocess(struct rule_pp_ctx *ctx,
 				       const struct expr *expr,
 				       enum proto_bases base)
@@ -1407,7 +1475,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) {
-			if (payload_dependency_exists(&ctx->pdctx, base))
+			if (payload_dependency_exists(&ctx->pdctx, base) &&
+			    meta_may_dependency_kill(&ctx->pdctx,
+						     ctx->pctx.family, expr))
 				payload_dependency_release(&ctx->pdctx);
 			if (left->flags & EXPR_F_PROTOCOL)
 				payload_dependency_store(&ctx->pdctx, ctx->stmt, base);
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux