Bug 88450

Summary: SYN+ACK reports strange size of window
Product: Base System Reporter: Maxim Podberezny <diascan>
Component: kernAssignee: Andre Oppermann <andre>
Status: Closed Overcome By Events    
Severity: Affects Only Me CC: jpaetzel
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description Maxim Podberezny 2005-11-03 12:50:26 UTC
              I test a newly ported FreeBSD TCP/IP stack at our OS. Stack was ported 'as is'. The test is performed with ANVL test suite.
The problem is that one of ANVL test performes the follows:
1. ANVL sends SYN to DUT (target with our OS)
2. DUT sends SYN+ACK with Window_From_DUT=0x4000
3. ANVL sends ACK to DUT.

now the state of the connection is ESTABLISHED.

4. ANVL sends SYN packet to DUT with unacceptable sequence number.
ANVL calculates the sequence number as follows:
SEQ = Seq_From_DUT + Window_From_DUT + 2

ANVL expects from DUT to receive ACK with some sequence number, but it receives RST. I investigated the issue and found that the size of window is calculated in syncache_add()-function:
1.1          (jlemon   22-Nov-01):      /* Initial receive window: clip sbspace to [0 .. TCP_MAXWIN] */
1.1          (jlemon   22-Nov-01):      win = sbspace(&so->so_rcv);
1.1          (jlemon   22-Nov-01):      win = imax(win, 0);
1.1          (jlemon   22-Nov-01):      win = imin(win, TCP_MAXWIN);
1.1          (jlemon   22-Nov-01):      sc->sc_wnd = win;

and uses this value when send the SYN+ACK in syncache_respond():
1.1          (jlemon   22-Nov-01):      th->th_x2 = 0;
1.1          (jlemon   22-Nov-01):      th->th_flags = TH_SYN|TH_ACK;
1.1          (jlemon   22-Nov-01):      th->th_win = htons(sc->sc_wnd);
1.1          (jlemon   22-Nov-01):      th->th_urp = 0;

After DUT has sended the SYN+ACK and received the last ACK, the size of window changed to a value of 0x40e8 in tcp_input.c file.

So, finally the unacceptable sequence number from ANVL is accepted in by DUT window, since 0x40e8 is bigger than 0x4000+2. DUT sends RST instead of ACK packet.

The situation that the window size has changed is correct, I now, but why this size is also changed by another algorithm in another file absolutely independently?

Before syncache was developed the receive window size was calculated always in one file in tcp_input.c.
The chain was as follows:
tcp_input()
 |
 |->tcp_dooptions()
   |
   |->tcp_mss()
The latter function changed the window size keeping integrity of the value.

Fix: 

If it's a bug or "wrong' issue I suggest to use the code from tcp_mss() function which was used earlier.

What do you think?
How-To-Repeat:               Establish a connection with FreeBSD and send SYN packet with sequence number bigger than in packet plus window and plus 2.
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2005-11-03 14:45:54 UTC
Responsible Changed
From-To: freebsd-ports-bugs->freebsd-bugs

This is definitely not a 'ports' problem, although I don't know exactly 
how to categorize it in this case ...
Comment 2 Tilman Keskinoz freebsd_committer freebsd_triage 2005-11-03 15:29:18 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-net

Over to -net for review
Comment 3 Andre Oppermann freebsd_committer freebsd_triage 2006-01-24 18:25:48 UTC
Responsible Changed
From-To: freebsd-net->andre

take over.