Commit 73327d47 authored by wenxu's avatar wenxu Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_flow_table_offload: fix the nat port mangle.



Shift on 32-bit word to define the port number depends on the flow
direction.

Fixes: c29f74e0 ("netfilter: nf_flow_table: hardware offload support")
Fixes: 7acd9378 ("netfilter: nf_flow_table_offload: Correct memcpy size for flow_overload_mangle()")
Signed-off-by: default avatarwenxu <wenxu@ucloud.cn>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent f31ad71c
Loading
Loading
Loading
Loading
+16 −8
Original line number Original line Diff line number Diff line
@@ -349,22 +349,26 @@ static void flow_offload_port_snat(struct net *net,
				   struct nf_flow_rule *flow_rule)
				   struct nf_flow_rule *flow_rule)
{
{
	struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
	struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
	u32 mask = ~htonl(0xffff0000), port;
	u32 mask, port;
	u32 offset;
	u32 offset;


	switch (dir) {
	switch (dir) {
	case FLOW_OFFLOAD_DIR_ORIGINAL:
	case FLOW_OFFLOAD_DIR_ORIGINAL:
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
		offset = 0; /* offsetof(struct tcphdr, source); */
		offset = 0; /* offsetof(struct tcphdr, source); */
		port = htonl(port << 16);
		mask = ~htonl(0xffff0000);
		break;
		break;
	case FLOW_OFFLOAD_DIR_REPLY:
	case FLOW_OFFLOAD_DIR_REPLY:
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
		offset = 0; /* offsetof(struct tcphdr, dest); */
		offset = 0; /* offsetof(struct tcphdr, dest); */
		port = htonl(port);
		mask = ~htonl(0xffff);
		break;
		break;
	default:
	default:
		return;
		return;
	}
	}
	port = htonl(port << 16);

	flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
	flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
			    &port, &mask);
			    &port, &mask);
}
}
@@ -375,22 +379,26 @@ static void flow_offload_port_dnat(struct net *net,
				   struct nf_flow_rule *flow_rule)
				   struct nf_flow_rule *flow_rule)
{
{
	struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
	struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
	u32 mask = ~htonl(0xffff), port;
	u32 mask, port;
	u32 offset;
	u32 offset;


	switch (dir) {
	switch (dir) {
	case FLOW_OFFLOAD_DIR_ORIGINAL:
	case FLOW_OFFLOAD_DIR_ORIGINAL:
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);
		offset = 0; /* offsetof(struct tcphdr, source); */
		offset = 0; /* offsetof(struct tcphdr, dest); */
		port = htonl(port);
		mask = ~htonl(0xffff);
		break;
		break;
	case FLOW_OFFLOAD_DIR_REPLY:
	case FLOW_OFFLOAD_DIR_REPLY:
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
		port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port);
		offset = 0; /* offsetof(struct tcphdr, dest); */
		offset = 0; /* offsetof(struct tcphdr, source); */
		port = htonl(port << 16);
		mask = ~htonl(0xffff0000);
		break;
		break;
	default:
	default:
		return;
		return;
	}
	}
	port = htonl(port);

	flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
	flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
			    &port, &mask);
			    &port, &mask);
}
}