diff options
author | Andrey Vagin <avagin@openvz.org> | 2012-09-19 05:40:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-20 17:49:58 -0400 |
commit | bc26ccd8fc756749de95606d28314efd0ce5aec3 (patch) | |
tree | 7415996141c9777b09f0d33ca90283bc44a40632 | |
parent | 8ea853fd0b721f14eacff1a5b364fe3e60d2dd82 (diff) |
tcp: restore rcv_wscale in a repair mode (v2)
rcv_wscale is a symetric parameter with snd_wscale.
Both this parameters are set on a connection handshake.
Without this value a remote window size can not be interpreted correctly,
because a value from a packet should be shifted on rcv_wscale.
And one more thing is that wscale_ok should be set too.
This patch doesn't break a backward compatibility.
If someone uses it in a old scheme, a rcv window
will be restored with the same bug (rcv_wscale = 0).
v2: Save backward compatibility on big-endian system. Before
the first two bytes were snd_wscale and the second two bytes were
rcv_wscale. Now snd_wscale is opt_val & 0xFFFF and rcv_wscale >> 16.
This approach is independent on byte ordering.
Cc: David S. Miller <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: James Morris <jmorris@namei.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Patrick McHardy <kaber@trash.net>
CC: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Vagin <avagin@openvz.org>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/tcp.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index bf9a8ab29459..5f6419341821 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2331,10 +2331,17 @@ static int tcp_repair_options_est(struct tcp_sock *tp, | |||
2331 | tp->rx_opt.mss_clamp = opt.opt_val; | 2331 | tp->rx_opt.mss_clamp = opt.opt_val; |
2332 | break; | 2332 | break; |
2333 | case TCPOPT_WINDOW: | 2333 | case TCPOPT_WINDOW: |
2334 | if (opt.opt_val > 14) | 2334 | { |
2335 | return -EFBIG; | 2335 | u16 snd_wscale = opt.opt_val & 0xFFFF; |
2336 | u16 rcv_wscale = opt.opt_val >> 16; | ||
2337 | |||
2338 | if (snd_wscale > 14 || rcv_wscale > 14) | ||
2339 | return -EFBIG; | ||
2336 | 2340 | ||
2337 | tp->rx_opt.snd_wscale = opt.opt_val; | 2341 | tp->rx_opt.snd_wscale = snd_wscale; |
2342 | tp->rx_opt.rcv_wscale = rcv_wscale; | ||
2343 | tp->rx_opt.wscale_ok = 1; | ||
2344 | } | ||
2338 | break; | 2345 | break; |
2339 | case TCPOPT_SACK_PERM: | 2346 | case TCPOPT_SACK_PERM: |
2340 | if (opt.opt_val != 0) | 2347 | if (opt.opt_val != 0) |