[comp.bugs.4bsd.ucb-fixes] ARTICLE 5

bostic@OKEEFFE.BERKELEY.EDU.UUCP (03/20/87)

4.3BSD network bug (#1, tcp_output)
Index:	sys/netinet/tcp_output.c 4.3BSD FIX

Description:
The final change in the send code in TCP in 4.3 was made incorrectly.
In tcp_output (/sys/netinet/tcp_output.c), the output packet flags
are chosen before the packet length is adjusted to reflect the maximum
segment size.  Under some cirsumstances, this results in sending a FIN
with a packet which is not the last data packet.  This is most often
noticed when the connection implements a one-way transfer of data
and the sender closes while the data is still draining; the result is
unnoticed loss of data.

Fix:
Move the lines in tcp_output that look up the flags to be sent
to a location after the final length adjustment, as follows:

*** /nbsd/sys/netinet/tcp_output.c	Thu Jun  5 00:31:36 1986
--- tcp_output.c	Wed Aug 20 09:31:34 1986
***************
*** 5,7 ****
   *
!  *	@(#)tcp_output.c	7.1 (Berkeley) 6/5/86
   */
--- 5,7 ----
   *
!  *	@(#)tcp_output.c	7.2 (Berkeley) 8/20/86
   */
***************
*** 82,85 ****
  	flags = tcp_outflags[tp->t_state];
- 	if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
- 		flags &= ~TH_FIN;
  
--- 82,83 ----
***************
*** 118,119 ****
--- 116,119 ----
  	}
+ 	if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
+ 		flags &= ~TH_FIN;
  	win = sbspace(&so->so_rcv);