364-v4.18-netfilter-nf_flow_table-tear-down-TCP-flows-if-RST-o.patch 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. Allow the slow path to handle the shutdown of the connection with proper
  6. timeouts
  7. Signed-off-by: Felix Fietkau <nbd@nbd.name>
  8. ---
  9. --- a/net/netfilter/nf_flow_table_ip.c
  10. +++ b/net/netfilter/nf_flow_table_ip.c
  11. @@ -15,6 +15,23 @@
  12. #include <linux/tcp.h>
  13. #include <linux/udp.h>
  14. +static int nf_flow_tcp_state_check(struct flow_offload *flow,
  15. + struct sk_buff *skb, unsigned int thoff)
  16. +{
  17. + struct tcphdr *tcph;
  18. +
  19. + if (!pskb_may_pull(skb, thoff + sizeof(*tcph)))
  20. + return -1;
  21. +
  22. + tcph = (void *)(skb_network_header(skb) + thoff);
  23. + if (unlikely(tcph->fin || tcph->rst)) {
  24. + flow_offload_teardown(flow);
  25. + return -1;
  26. + }
  27. +
  28. + return 0;
  29. +}
  30. +
  31. static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
  32. __be32 addr, __be32 new_addr)
  33. {
  34. @@ -118,10 +135,9 @@ static int nf_flow_dnat_ip(const struct
  35. }
  36. static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
  37. - enum flow_offload_tuple_dir dir)
  38. + unsigned int thoff, enum flow_offload_tuple_dir dir)
  39. {
  40. struct iphdr *iph = ip_hdr(skb);
  41. - unsigned int thoff = iph->ihl * 4;
  42. if (flow->flags & FLOW_OFFLOAD_SNAT &&
  43. (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
  44. @@ -201,6 +217,7 @@ nf_flow_offload_ip_hook(void *priv, stru
  45. struct flow_offload *flow;
  46. struct net_device *outdev;
  47. const struct rtable *rt;
  48. + unsigned int thoff;
  49. struct iphdr *iph;
  50. __be32 nexthop;
  51. @@ -229,8 +246,12 @@ nf_flow_offload_ip_hook(void *priv, stru
  52. if (skb_try_make_writable(skb, sizeof(*iph)))
  53. return NF_DROP;
  54. + thoff = ip_hdr(skb)->ihl * 4;
  55. + if (nf_flow_tcp_state_check(flow, skb, thoff))
  56. + return NF_ACCEPT;
  57. +
  58. if (flow->flags & (FLOW_OFFLOAD_SNAT | FLOW_OFFLOAD_DNAT) &&
  59. - nf_flow_nat_ip(flow, skb, dir) < 0)
  60. + nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
  61. return NF_DROP;
  62. flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
  63. @@ -438,6 +459,9 @@ nf_flow_offload_ipv6_hook(void *priv, st
  64. if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
  65. return NF_ACCEPT;
  66. + if (nf_flow_tcp_state_check(flow, skb, sizeof(*ip6h)))
  67. + return NF_ACCEPT;
  68. +
  69. if (skb_try_make_writable(skb, sizeof(*ip6h)))
  70. return NF_DROP;