netfilter: nf_flow_table_offload: fix the nat port mangle.
authorwenxu <wenxu@ucloud.cn>
Fri, 20 Dec 2019 04:14:38 +0000 (12:14 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 5 Jan 2020 09:06:34 +0000 (10:06 +0100)
Shift on 32-bit word to define the port number depends on the flow
direction.

Fixes: c29f74e0df7a ("netfilter: nf_flow_table: hardware offload support")
Fixes: 7acd9378dc652 ("netfilter: nf_flow_table_offload: Correct memcpy size for flow_overload_mangle()")
Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_flow_table_offload.c

index 92b0bd2410731c178d5a3c2d9433f7cdab41f17a..6c162c954c4fd0c5a8f69e86bcace3cbb1016cbf 100644 (file)
@@ -349,22 +349,26 @@ static void flow_offload_port_snat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff0000), port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
                port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
                offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
                port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
                offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        default:
                return;
        }
-       port = htonl(port << 16);
+
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
                            &port, &mask);
 }
@@ -375,22 +379,26 @@ static void flow_offload_port_dnat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff), port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
-               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);
+               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
-               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port);
+               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        default:
                return;
        }
-       port = htonl(port);
+
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
                            &port, &mask);
 }