Fix a bug (apparently very old) that can cause a TCP connection to

be dropped when it has an unusual traffic pattern.  For full details
as well as a test case that demonstrates the failure, see the
referenced PR.

Under certain circumstances involving the persist state, it is
possible for the receive side's tp->rcv_nxt to advance beyond its
tp->rcv_adv.  This causes (tp->rcv_adv - tp->rcv_nxt) to become
negative.  However, in the code affected by this fix, that difference
was interpreted as an unsigned number by max().  Since it was
negative, it was taken as a huge unsigned number.  The effect was
to cause the receiver to believe that its receive window had negative
size, thereby rejecting all received segments including ACKs.  As
the test case shows, this led to fruitless retransmissions and
eventually to a dropped connection.  Even connections using the
loopback interface could be dropped.  The fix substitutes the signed
imax() for the unsigned max() function.

PR:		closes kern/3998
Reviewed by:	davidg, fenner, wollman
This commit is contained in:
John Polstra 1997-07-01 05:42:16 +00:00
parent 0395b68640
commit 66e39adc7c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27135
2 changed files with 4 additions and 4 deletions

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
* $Id: tcp_input.c,v 1.57 1997/02/22 09:41:40 peter Exp $
* $Id: tcp_input.c,v 1.58 1997/04/27 20:01:13 wollman Exp $
*/
#ifndef TUBA_INCLUDE
@ -604,7 +604,7 @@ tcp_input(m, iphlen)
win = sbspace(&so->so_rcv);
if (win < 0)
win = 0;
tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
}
switch (tp->t_state) {

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
* $Id: tcp_input.c,v 1.57 1997/02/22 09:41:40 peter Exp $
* $Id: tcp_input.c,v 1.58 1997/04/27 20:01:13 wollman Exp $
*/
#ifndef TUBA_INCLUDE
@ -604,7 +604,7 @@ tcp_input(m, iphlen)
win = sbspace(&so->so_rcv);
if (win < 0)
win = 0;
tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
}
switch (tp->t_state) {