summaryrefslogtreecommitdiffstats
path: root/src/net/tcp.c
diff options
context:
space:
mode:
authorMichael Brown2007-01-03 22:51:36 +0100
committerMichael Brown2007-01-03 22:51:36 +0100
commiteea1167a85e3f7a3d244a5aaa55a9ba624aec07b (patch)
tree06b22c36a02122d8859fbfd744caea1606ea1449 /src/net/tcp.c
parentImprove consistency between TCP and UDP RX datapaths (diff)
downloadipxe-eea1167a85e3f7a3d244a5aaa55a9ba624aec07b.tar.gz
ipxe-eea1167a85e3f7a3d244a5aaa55a9ba624aec07b.tar.xz
ipxe-eea1167a85e3f7a3d244a5aaa55a9ba624aec07b.zip
Accept RST on received packets
Diffstat (limited to 'src/net/tcp.c')
-rw-r--r--src/net/tcp.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/src/net/tcp.c b/src/net/tcp.c
index 8b56604a..579495c3 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -559,7 +559,8 @@ static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
return 0;
}
-/** Handle TCP received FIN
+/**
+ * Handle TCP received FIN
*
* @v conn TCP connection
* @v seq SEQ value (in host-endian order)
@@ -588,6 +589,46 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
}
/**
+ * Handle TCP received RST
+ *
+ * @v conn TCP connection
+ * @v seq SEQ value (in host-endian order)
+ * @ret rc Return status code
+ */
+static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
+ struct tcp_application *app = conn->app;
+
+ /* Accept RST only if it falls within the window. If we have
+ * not yet received a SYN, then we have no window to test
+ * against, so fall back to checking that our SYN has been
+ * ACKed.
+ */
+ if ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
+ if ( ( conn->rcv_ack - seq ) > 0 )
+ return 0;
+ } else {
+ if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ return 0;
+ }
+
+ /* Transition to CLOSED */
+ conn->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( conn );
+
+ /* Break association between application and connection */
+ tcp_disassociate ( conn );
+
+ /* Free the connection */
+ free_tcp ( conn );
+
+ /* Notify application */
+ if ( app && app->tcp_op->closed )
+ app->tcp_op->closed ( app, -ECONNRESET );
+
+ return -ECONNRESET;
+}
+
+/**
* Process received packet
*
* @v pkb Packet buffer
@@ -668,13 +709,6 @@ static int tcp_rx ( struct pk_buff *pkb,
goto done;
}
- /* Handle RST, if present */
-#warning "Handle RST"
- if ( flags & TCP_RST ) {
- rc = -ECONNRESET;
- goto done;
- }
-
/* Handle ACK, if present */
if ( flags & TCP_ACK )
tcp_rx_ack ( conn, ack, win );
@@ -685,6 +719,12 @@ static int tcp_rx ( struct pk_buff *pkb,
seq++;
}
+ /* Handle RST, if present */
+ if ( flags & TCP_RST ) {
+ if ( ( rc = tcp_rx_rst ( conn, seq ) ) != 0 )
+ goto done;
+ }
+
/* Handle new data, if any */
tcp_rx_data ( conn, seq, data, len );
seq += len;
@@ -695,7 +735,7 @@ static int tcp_rx ( struct pk_buff *pkb,
seq++;
}
- /* Dump out any state change as a result of SYN, FIN or ACK */
+ /* Dump out any state change as a result of the received packet */
tcp_dump_state ( conn );
/* Send out any pending data. If peer is expecting an ACK for