OpenWrt – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Felix Fietkau <nbd@nbd.name> |
2 | Date: Sun, 25 Feb 2018 15:42:58 +0100 |
||
3 | Subject: [PATCH] netfilter: nf_flow_table: tear down TCP flows if RST or |
||
4 | FIN was seen |
||
5 | |||
6 | Allow the slow path to handle the shutdown of the connection with proper |
||
7 | timeouts |
||
8 | |||
9 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
||
10 | --- |
||
11 | |||
12 | --- a/net/netfilter/nf_flow_table_ip.c |
||
13 | +++ b/net/netfilter/nf_flow_table_ip.c |
||
14 | @@ -15,6 +15,23 @@ |
||
15 | #include <linux/tcp.h> |
||
16 | #include <linux/udp.h> |
||
17 | |||
18 | +static int nf_flow_tcp_state_check(struct flow_offload *flow, |
||
19 | + struct sk_buff *skb, unsigned int thoff) |
||
20 | +{ |
||
21 | + struct tcphdr *tcph; |
||
22 | + |
||
23 | + if (!pskb_may_pull(skb, thoff + sizeof(*tcph))) |
||
24 | + return -1; |
||
25 | + |
||
26 | + tcph = (void *)(skb_network_header(skb) + thoff); |
||
27 | + if (unlikely(tcph->fin || tcph->rst)) { |
||
28 | + flow_offload_teardown(flow); |
||
29 | + return -1; |
||
30 | + } |
||
31 | + |
||
32 | + return 0; |
||
33 | +} |
||
34 | + |
||
35 | static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, |
||
36 | __be32 addr, __be32 new_addr) |
||
37 | { |
||
38 | @@ -118,10 +135,9 @@ static int nf_flow_dnat_ip(const struct |
||
39 | } |
||
40 | |||
41 | static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, |
||
42 | - enum flow_offload_tuple_dir dir) |
||
43 | + unsigned int thoff, enum flow_offload_tuple_dir dir) |
||
44 | { |
||
45 | struct iphdr *iph = ip_hdr(skb); |
||
46 | - unsigned int thoff = iph->ihl * 4; |
||
47 | |||
48 | if (flow->flags & FLOW_OFFLOAD_SNAT && |
||
49 | (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 || |
||
50 | @@ -201,6 +217,7 @@ nf_flow_offload_ip_hook(void *priv, stru |
||
51 | struct flow_offload *flow; |
||
52 | struct net_device *outdev; |
||
53 | const struct rtable *rt; |
||
54 | + unsigned int thoff; |
||
55 | struct iphdr *iph; |
||
56 | __be32 nexthop; |
||
57 | |||
58 | @@ -229,8 +246,12 @@ nf_flow_offload_ip_hook(void *priv, stru |
||
59 | if (skb_try_make_writable(skb, sizeof(*iph))) |
||
60 | return NF_DROP; |
||
61 | |||
62 | + thoff = ip_hdr(skb)->ihl * 4; |
||
63 | + if (nf_flow_tcp_state_check(flow, skb, thoff)) |
||
64 | + return NF_ACCEPT; |
||
65 | + |
||
66 | if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) && |
||
67 | - nf_flow_nat_ip(flow, skb, dir) < 0) |
||
68 | + nf_flow_nat_ip(flow, skb, thoff, dir) < 0) |
||
69 | return NF_DROP; |
||
70 | |||
71 | flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; |
||
72 | @@ -438,6 +459,9 @@ nf_flow_offload_ipv6_hook(void *priv, st |
||
73 | if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) |
||
74 | return NF_ACCEPT; |
||
75 | |||
76 | + if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h))) |
||
77 | + return NF_ACCEPT; |
||
78 | + |
||
79 | if (skb_try_make_writable(skb, sizeof(*ip6h))) |
||
80 | return NF_DROP; |
||
81 |