From 3f442d3f601306f97d21a8716ea303ee053822d1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 26 Mar 2011 14:58:17 +0000 Subject: [PATCH] [tcp] Record ts_recent on first received packet Commit 6861304 ("[tcp] Handle out-of-order received packets") introduced a regression in which ts_recent would not be updated until the first packet is received in the ESTABLISHED state, i.e. the timestamp from the SYN+ACK packet would be ignored. This causes the connection to be dropped by strictly-conforming TCP peers, such as FreeBSD. Fix by delaying the timestamp window check until after processing the received SYN flag. Reported-by: winders@sonnet.com Signed-off-by: Michael Brown --- src/net/tcp.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/net/tcp.c b/src/net/tcp.c index 3e1aeedc..d9529882 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -1060,6 +1060,7 @@ static int tcp_rx ( struct io_buffer *iobuf, struct tcp_options options; size_t hlen; uint16_t csum; + uint32_t start_seq; uint32_t seq; uint32_t ack; uint32_t win; @@ -1099,7 +1100,7 @@ static int tcp_rx ( struct io_buffer *iobuf, /* Parse parameters from header and strip header */ tcp = tcp_demux ( ntohs ( tcphdr->dest ) ); - seq = ntohl ( tcphdr->seq ); + seq = start_seq = ntohl ( tcphdr->seq ); ack = ntohl ( tcphdr->ack ); win = ntohs ( tcphdr->win ); flags = tcphdr->flags; @@ -1125,10 +1126,6 @@ static int tcp_rx ( struct io_buffer *iobuf, goto discard; } - /* Update timestamp, if applicable */ - if ( options.tsopt && tcp_in_window ( tcp->rcv_ack, seq, seq_len ) ) - tcp->ts_recent = ntohl ( options.tsopt->tsval ); - /* Handle ACK, if present */ if ( flags & TCP_ACK ) { if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) { @@ -1155,6 +1152,12 @@ static int tcp_rx ( struct io_buffer *iobuf, goto discard; } + /* Update timestamp, if applicable */ + if ( options.tsopt && + tcp_in_window ( tcp->rcv_ack, start_seq, seq_len ) ) { + tcp->ts_recent = ntohl ( options.tsopt->tsval ); + } + /* Enqueue received data */ tcp_rx_enqueue ( tcp, seq, flags, iob_disown ( iobuf ) );