[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