TCP and syncache question

Hartmut Brandt hartmut.brandt at
Fri Nov 21 04:10:28 PST 2008

Andre Oppermann wrote:
> Harti Brandt wrote:
>> Hi Andre,
>> On Mon, 17 Nov 2008, Andre Oppermann wrote:
>> AO>This is a bit more complicated because of interactions with 
>> tcp_input()
>> AO>where syncache_expand() is called from.
>> AO>
>> AO>The old code (as of December 2002) behaved slightly different.  It 
>> would
>> AO>not remove the syncache entry when (SND.UNA == SEG.ACK) but send a 
>> RST.
>> AO>The (RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND) test wasn't 
>> done at
>> AO>all.  Instead a socket was opened whenever (SND.UNA == SEG.ACK) 
>> succeeded.
>> AO>This gave way to the "LAND" DoS attack which was mostly fixed with 
>> a test
>> AO>for (RCV.IRS < SEG.SEQ).
>> AO>
>> AO>See the attached patch for fixed version of syncache_expand().  
>> This patch
>> AO>is untested though.  My development machine is currently down.  
>> Harti, Rui
>> AO>and Bjoern, please have a look at the patch and review it.
>> Some small problems:
> ...
>> Need another cast here: *lsop = (struct socket *)1.
> Changed the logic to use a NULL *lsop to differentiate in tcp_input().
> Much simpler
Indeed. But now the code sends a SYN+ACK with seqno == iss which is 
contrary to p.69 which requires ACK only and seqno == snd_nxt == iss + 1 
(in our case).

On the other hand one could point to the example on p. 33 (fig. 9), 
although it is not entirely clear from the figure whether the SYN in 
line 2 actually moves TCP B to SYN-RECEIVED. In any case I checked both 
our pre-syncache code and OpenSolaris and both of them seem to send only 
the ACK (I did not try it, just read the code).
> .
>> [snip]
>> I've re-run my test scripts and they seem to indicate, that the 
>> socket is
>> now kept in the correct state when the incoming segment had an incorrect
>> ack. I could no yet run the tests for an incorrect seqno, though. 
>> This is
>> because there is an interesting problem in RFC793 (and MIL-STD-1778): 
>> the RFC
>> states on page 36 a general rule that a 'reset (RST) must be sent 
>> whenever
>> a segment arrives which apparently is not intended for the current 
>> connection.'
> The full quote from page 36 is: "As a general rule, reset (RST) must 
> be sent
> whenever a segment arrives which apparently is not intended for the 
> current
> connection.  A reset must not be sent if it is not clear that this is 
> the case."
>> I would say, that a segment carrying a sequence number at irs (when 
>> without SYN)
>> and below irs (in any case) cannot belong to the current connection - 
>> those
>> sequence numbers just don't exist for the connection. On the other 
>> hand p.69
>> says that we must send an ACK. If this were an ITU-T standard, things
>> would be clear, because the prosa description would be normative, not 
>> the
>> algorithm.
> The more specific rule wins.  Sending the "challenge" ACK is done 
> under the
> assumption that the remote end will send a reset to our "challenge" 
> ACK if
> such an connection doesn't exist there.
Well, at least in the last pre-syncache revision (tcp_input.c rev. 
1.142) there is the sequence number check on line 1580, that was 
introduced in rev. 1.81 to prevent the "land" attack, that sends an RST 
when th_seq <= irs. Confusingly enough that test is still there (now at 
line 1610) but, as far as I can see never reached (because of syncache). 
It also is th_seq < irs now for some reasons.


More information about the freebsd-net mailing list