[gPXE-devel] [PATCHv4 07/10] [tcp] Fix possible misjudged SYN/FIN ACKed status
Guo-Fu Tseng
cooldavid at cooldavid.org
Sat Jul 17 21:26:12 EDT 2010
From: Guo-Fu Tseng <cooldavid at cooldavid.org>
gPXE did not check the ACK number while receiving a response from remote
server with ACK flag set. gPXE assumes the remote server ACKed the
SYN/FIN sent by gPXE if received ANY packet with ACK flag being set.
This error might occur when the packet is out-of-order.
Signed-off-by: Guo-Fu Tseng <cooldavid at cooldavid.org>
---
src/net/tcp.c | 26 +++++++++++++++++++++++---
1 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/net/tcp.c b/src/net/tcp.c
index 8c5203c..f25a83e 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -63,6 +63,17 @@ struct tcp_connection {
* Equivalent to SND.WND in RFC 793 terminology
*/
uint32_t snd_win;
+ /** Send SYN sequence
+ *
+ * Sequence number of sent SYN packet
+ */
+ uint32_t snd_syn_seq;
+ /** Send FIN sequence
+ *
+ * Sequence number of sent FIN packet
+ */
+ uint32_t snd_fin_seq;
+
/** Current acknowledgement number
*
* Equivalent to RCV.NXT in RFC 793 terminology.
@@ -541,6 +552,11 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
return rc;
}
+ if ( flags & TCP_SYN )
+ tcp->snd_syn_seq = tcp->snd_seq;
+ if ( flags & TCP_FIN )
+ tcp->snd_fin_seq = tcp->snd_seq;
+
return 0;
}
@@ -761,7 +777,7 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
uint32_t win ) {
uint32_t ack_len = ( ack - tcp->snd_seq );
size_t len;
- unsigned int acked_flags;
+ unsigned int acked_flags = 0;
/* Check for out-of-range or old duplicate ACKs */
if ( ack_len > tcp->snd_sent ) {
@@ -796,8 +812,12 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
/* Determine acknowledged flags and data length */
len = ack_len;
- acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
- ( TCP_SYN | TCP_FIN ) );
+ if ( ( TCP_FLAGS_SENDING ( tcp->tcp_state ) & TCP_SYN ) &&
+ after ( ack, tcp->snd_syn_seq ) )
+ acked_flags |= TCP_SYN;
+ if ( ( TCP_FLAGS_SENDING ( tcp->tcp_state ) & TCP_FIN ) &&
+ after ( ack, tcp->snd_fin_seq ) )
+ acked_flags |= TCP_FIN;
if ( acked_flags )
len--;
--
1.7.1
More information about the gPXE-devel
mailing list