Skip to content

Commit 4c67525

Browse files
Alexey Kuznetsovdavem330
authored andcommitted
tcp: resets are misrouted
After commit e2446ea ("tcp_v4_send_reset: binding oif to iif in no sock case").. tcp resets are always lost, when routing is asymmetric. Yes, backing out that patch will result in misrouting of resets for dead connections which used interface binding when were alive, but we actually cannot do anything here. What's died that's died and correct handling normal unbound connections is obviously a priority. Comment to comment: > This has few benefits: > 1. tcp_v6_send_reset already did that. It was done to route resets for IPv6 link local addresses. It was a mistake to do so for global addresses. The patch fixes this as well. Actually, the problem appears to be even more serious than guaranteed loss of resets. As reported by Sergey Soloviev <[email protected]>, those misrouted resets create a lot of arp traffic and huge amount of unresolved arp entires putting down to knees NAT firewalls which use asymmetric routing. Signed-off-by: Alexey Kuznetsov <[email protected]>
1 parent 5d9d01a commit 4c67525

File tree

2 files changed

+6
-4
lines changed

2 files changed

+6
-4
lines changed

net/ipv4/tcp_ipv4.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -708,10 +708,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
708708
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
709709
arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
710710
/* When socket is gone, all binding information is lost.
711-
* routing might fail in this case. using iif for oif to
712-
* make sure we can deliver it
711+
* routing might fail in this case. No choice here, if we choose to force
712+
* input interface, we will misroute in case of asymmetric route.
713713
*/
714-
arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
714+
if (sk)
715+
arg.bound_dev_if = sk->sk_bound_dev_if;
715716

716717
net = dev_net(skb_dst(skb)->dev);
717718
arg.tos = ip_hdr(skb)->tos;

net/ipv6/tcp_ipv6.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
877877
__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
878878

879879
fl6.flowi6_proto = IPPROTO_TCP;
880-
fl6.flowi6_oif = inet6_iif(skb);
880+
if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
881+
fl6.flowi6_oif = inet6_iif(skb);
881882
fl6.fl6_dport = t1->dest;
882883
fl6.fl6_sport = t1->source;
883884
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));

0 commit comments

Comments
 (0)