|
@@ -559,7 +559,8 @@ static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
|
559
|
559
|
return 0;
|
560
|
560
|
}
|
561
|
561
|
|
562
|
|
-/** Handle TCP received FIN
|
|
562
|
+/**
|
|
563
|
+ * Handle TCP received FIN
|
563
|
564
|
*
|
564
|
565
|
* @v conn TCP connection
|
565
|
566
|
* @v seq SEQ value (in host-endian order)
|
|
@@ -587,6 +588,46 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
|
587
|
588
|
return 0;
|
588
|
589
|
}
|
589
|
590
|
|
|
591
|
+/**
|
|
592
|
+ * Handle TCP received RST
|
|
593
|
+ *
|
|
594
|
+ * @v conn TCP connection
|
|
595
|
+ * @v seq SEQ value (in host-endian order)
|
|
596
|
+ * @ret rc Return status code
|
|
597
|
+ */
|
|
598
|
+static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
|
|
599
|
+ struct tcp_application *app = conn->app;
|
|
600
|
+
|
|
601
|
+ /* Accept RST only if it falls within the window. If we have
|
|
602
|
+ * not yet received a SYN, then we have no window to test
|
|
603
|
+ * against, so fall back to checking that our SYN has been
|
|
604
|
+ * ACKed.
|
|
605
|
+ */
|
|
606
|
+ if ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
|
|
607
|
+ if ( ( conn->rcv_ack - seq ) > 0 )
|
|
608
|
+ return 0;
|
|
609
|
+ } else {
|
|
610
|
+ if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
|
|
611
|
+ return 0;
|
|
612
|
+ }
|
|
613
|
+
|
|
614
|
+ /* Transition to CLOSED */
|
|
615
|
+ conn->tcp_state = TCP_CLOSED;
|
|
616
|
+ tcp_dump_state ( conn );
|
|
617
|
+
|
|
618
|
+ /* Break association between application and connection */
|
|
619
|
+ tcp_disassociate ( conn );
|
|
620
|
+
|
|
621
|
+ /* Free the connection */
|
|
622
|
+ free_tcp ( conn );
|
|
623
|
+
|
|
624
|
+ /* Notify application */
|
|
625
|
+ if ( app && app->tcp_op->closed )
|
|
626
|
+ app->tcp_op->closed ( app, -ECONNRESET );
|
|
627
|
+
|
|
628
|
+ return -ECONNRESET;
|
|
629
|
+}
|
|
630
|
+
|
590
|
631
|
/**
|
591
|
632
|
* Process received packet
|
592
|
633
|
*
|
|
@@ -668,13 +709,6 @@ static int tcp_rx ( struct pk_buff *pkb,
|
668
|
709
|
goto done;
|
669
|
710
|
}
|
670
|
711
|
|
671
|
|
- /* Handle RST, if present */
|
672
|
|
-#warning "Handle RST"
|
673
|
|
- if ( flags & TCP_RST ) {
|
674
|
|
- rc = -ECONNRESET;
|
675
|
|
- goto done;
|
676
|
|
- }
|
677
|
|
-
|
678
|
712
|
/* Handle ACK, if present */
|
679
|
713
|
if ( flags & TCP_ACK )
|
680
|
714
|
tcp_rx_ack ( conn, ack, win );
|
|
@@ -685,6 +719,12 @@ static int tcp_rx ( struct pk_buff *pkb,
|
685
|
719
|
seq++;
|
686
|
720
|
}
|
687
|
721
|
|
|
722
|
+ /* Handle RST, if present */
|
|
723
|
+ if ( flags & TCP_RST ) {
|
|
724
|
+ if ( ( rc = tcp_rx_rst ( conn, seq ) ) != 0 )
|
|
725
|
+ goto done;
|
|
726
|
+ }
|
|
727
|
+
|
688
|
728
|
/* Handle new data, if any */
|
689
|
729
|
tcp_rx_data ( conn, seq, data, len );
|
690
|
730
|
seq += len;
|
|
@@ -695,7 +735,7 @@ static int tcp_rx ( struct pk_buff *pkb,
|
695
|
735
|
seq++;
|
696
|
736
|
}
|
697
|
737
|
|
698
|
|
- /* Dump out any state change as a result of SYN, FIN or ACK */
|
|
738
|
+ /* Dump out any state change as a result of the received packet */
|
699
|
739
|
tcp_dump_state ( conn );
|
700
|
740
|
|
701
|
741
|
/* Send out any pending data. If peer is expecting an ACK for
|