Re: [RFC PATCH nft] payload: Don't kill dependency for proto_th

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

 



Xiao Liang <shaw.leon@xxxxxxxxx> wrote:
> Since proto_th carries no information about the proto number, we need to
> preserve the L4 protocol expression.
> 
> For example, if "meta l4proto 91 @th,0,16 0" is simplified to
> "th sport 0", the information of protocol number is lost. This patch
> changes it to "meta l4proto 91 th sport 0".
> 
> Signed-off-by: Xiao Liang <shaw.leon@xxxxxxxxx>
> ---
> 
> Technically, if port is not defined for the L4 protocol, it's better to
> keep "@th,0,16" as raw payload expressions rather than "th sport". But
> it's not easy to figure out the context.

Yes, this is also because we don't store dependencies like
'meta l4proto { tcp, udp }', so we don't have access to this info when
we see the @th,0,16 load.

What do you make of this (it will display @th syntax for your test case)?

diff --git a/src/payload.c b/src/payload.c
--- a/src/payload.c
+++ b/src/payload.c
@@ -851,6 +851,58 @@ static bool payload_may_dependency_kill_ll(struct payload_dep_ctx *ctx, struct e
 	return true;
 }
 
+static bool l4proto_has_ports(struct payload_dep_ctx *ctx, struct expr *expr)
+{
+	uint8_t v;
+
+	assert(expr->etype == EXPR_VALUE);
+
+	if (expr->len != 8)
+		return false;
+
+	v = mpz_get_uint8(expr->value);
+
+	switch (v) {
+	case IPPROTO_UDPLITE:
+	case IPPROTO_UDP:
+	case IPPROTO_TCP:
+	case IPPROTO_DCCP:
+	case IPPROTO_SCTP:
+		return true;
+	}
+
+	return false;
+}
+
+static bool payload_may_dependency_kill_th(struct payload_dep_ctx *ctx, struct expr *expr)
+{
+	struct expr *dep = payload_dependency_get(ctx, expr->payload.base);
+	enum proto_bases b;
+
+	switch (dep->left->etype) {
+	case EXPR_PAYLOAD:
+		b = dep->left->payload.base;
+		break;
+	case EXPR_META:
+		b = dep->left->meta.base;
+		break;
+	default:
+		return false;
+	}
+
+	if (b != PROTO_BASE_NETWORK_HDR)
+		return false;
+
+	switch (dep->right->etype) {
+	case EXPR_VALUE:
+		return l4proto_has_ports(ctx, dep->right);
+	default:
+		break;
+	}
+
+	return false;
+}
+
 static bool payload_may_dependency_kill(struct payload_dep_ctx *ctx,
 					unsigned int family, struct expr *expr)
 {
@@ -893,6 +945,15 @@ static bool payload_may_dependency_kill(struct payload_dep_ctx *ctx,
 	if (expr->payload.base != PROTO_BASE_TRANSPORT_HDR)
 		return true;
 
+	if (expr->payload.desc == &proto_th) {
+		if (payload_may_dependency_kill_th(ctx, expr))
+			return true;
+
+		/* prefer @th syntax, we don't have a 'source/destination port' protocol */
+		expr->payload.desc = &proto_unknown;
+		return false;
+	}
+
 	if (dep->left->etype != EXPR_PAYLOAD ||
 	    dep->left->payload.base != PROTO_BASE_TRANSPORT_HDR)
 		return true;


It would make sense to NOT set &proto_th from payload_init_raw(), but
that would place significant burden on netlink_delinearize to
pretty-print the typical use case for this, i.e.

'meta l4proto { tcp, udp } th dport 53 accept'





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux