|
@@ -329,6 +329,8 @@ void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
|
329
|
329
|
conn->tcp_lstate = conn->tcp_state;
|
330
|
330
|
conn->tcp_state = nxt_state;
|
331
|
331
|
|
|
332
|
+ DBG ( "Transition from %s to %s\n", tcp_states[conn->tcp_lstate], tcp_states[conn->tcp_state] );
|
|
333
|
+
|
332
|
334
|
/* TODO: Check if this check is required */
|
333
|
335
|
if ( conn->tcp_lstate == conn->tcp_state ||
|
334
|
336
|
conn->tcp_state == TCP_INVALID ) {
|
|
@@ -682,6 +684,7 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
|
682
|
684
|
tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
|
683
|
685
|
|
684
|
686
|
/* Dump the TCP header */
|
|
687
|
+ tcp_dump ( tcphdr );
|
685
|
688
|
|
686
|
689
|
/* Start the timer */
|
687
|
690
|
if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
|
|
@@ -719,24 +722,22 @@ static int tcp_rx ( struct pk_buff *pkb,
|
719
|
722
|
goto done;
|
720
|
723
|
}
|
721
|
724
|
|
722
|
|
-
|
723
|
725
|
/* Process TCP header */
|
724
|
726
|
tcphdr = pkb->data;
|
725
|
727
|
tcp_dump ( tcphdr );
|
726
|
728
|
|
727
|
729
|
/* Verify header length */
|
728
|
730
|
hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
|
|
731
|
+ if ( hlen < sizeof ( *tcphdr ) ) {
|
|
732
|
+ DBG ( "Bad header length (%d bytes)\n", hlen );
|
|
733
|
+ rc = -EINVAL;
|
|
734
|
+ goto done;
|
|
735
|
+ }
|
|
736
|
+ /* TODO: Parse TCP options */
|
729
|
737
|
if ( hlen != sizeof ( *tcphdr ) ) {
|
730
|
|
- if ( hlen == sizeof ( *tcphdr ) + 4 ) {
|
731
|
|
- DBG ( "TCP options sent\n" );
|
732
|
|
- } else {
|
733
|
|
- DBG ( "Bad header length (%d bytes)\n", hlen );
|
734
|
|
- rc = -EINVAL;
|
735
|
|
- goto done;
|
736
|
|
- }
|
|
738
|
+ DBG ( "Ignoring TCP options\n" );
|
737
|
739
|
}
|
738
|
740
|
|
739
|
|
-
|
740
|
741
|
/* TODO: Verify checksum */
|
741
|
742
|
|
742
|
743
|
/* Demux TCP connection */
|
|
@@ -828,16 +829,19 @@ static int tcp_rx ( struct pk_buff *pkb,
|
828
|
829
|
/* Unexpected packet */
|
829
|
830
|
goto unexpected;
|
830
|
831
|
case TCP_ESTABLISHED:
|
831
|
|
-#if 0
|
832
|
832
|
if ( tcphdr->flags & TCP_FIN ) {
|
833
|
|
- tcp_trans ( conn, TCP_CLOSE_WAIT );
|
|
833
|
+ if ( tcphdr->flags & TCP_ACK ) {
|
|
834
|
+ tcp_trans ( conn, TCP_LAST_ACK );
|
|
835
|
+ conn->tcp_flags |= TCP_FIN;
|
|
836
|
+ } else {
|
|
837
|
+ tcp_trans ( conn, TCP_CLOSE_WAIT );
|
|
838
|
+ }
|
834
|
839
|
/* FIN consumes one byte */
|
835
|
840
|
conn->rcv_nxt++;
|
836
|
841
|
conn->tcp_flags |= TCP_ACK;
|
837
|
|
- /* Send an acknowledgement */
|
|
842
|
+ /* Send the packet */
|
838
|
843
|
goto send_tcp_nomsg;
|
839
|
844
|
}
|
840
|
|
-#endif
|
841
|
845
|
/* Packet might contain data */
|
842
|
846
|
break;
|
843
|
847
|
case TCP_FIN_WAIT_1:
|
|
@@ -901,60 +905,45 @@ static int tcp_rx ( struct pk_buff *pkb,
|
901
|
905
|
assert ( ( tcphdr->flags & TCP_ACK ) ||
|
902
|
906
|
pkb_len ( pkb ) > sizeof ( *tcphdr ) );
|
903
|
907
|
|
904
|
|
- /* Check for new data */
|
905
|
|
- toack = pkb_len ( pkb ) - hlen;
|
906
|
|
- if ( toack > 0 ) {
|
907
|
|
- /* Check if expected sequence number */
|
908
|
|
- if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
|
909
|
|
- conn->rcv_nxt += toack;
|
910
|
|
- conn->tcp_op->newdata ( conn, pkb->data + hlen,
|
911
|
|
- toack );
|
912
|
|
- } else {
|
913
|
|
- DBG ( "Unexpected sequence number %lx (wanted %lx)\n",
|
914
|
|
- ntohl ( tcphdr->seq ), conn->rcv_nxt );
|
915
|
|
- }
|
916
|
|
-
|
917
|
|
- /* Acknowledge new data */
|
918
|
|
- conn->tcp_flags |= TCP_ACK;
|
919
|
|
- if ( !( tcphdr->flags & TCP_ACK ) ) {
|
920
|
|
- goto send_tcp_nomsg;
|
921
|
|
- }
|
922
|
|
- }
|
923
|
|
-
|
924
|
|
- /* Process ACK */
|
|
908
|
+ /**
|
|
909
|
+ * Check if the received packet ACKs sent data
|
|
910
|
+ */
|
925
|
911
|
if ( tcphdr->flags & TCP_ACK ) {
|
926
|
912
|
acked = ntohl ( tcphdr->ack ) - conn->snd_una;
|
927
|
|
- if ( acked < 0 ) { /* TODO: Replace all uint32_t arith */
|
928
|
|
- DBG ( "Previously ACKed (%d)\n", tcphdr->ack );
|
|
913
|
+ if ( acked < 0 ) {
|
|
914
|
+ /* Packet ACKs previously ACKed data */
|
|
915
|
+ DBG ( "Previously ACKed data %lx\n",
|
|
916
|
+ ntohl ( tcphdr->ack ) );
|
929
|
917
|
rc = 0;
|
930
|
918
|
goto done;
|
931
|
919
|
}
|
932
|
|
- /* Advance snd stream */
|
|
920
|
+ /* Invoke the acked() callback */
|
933
|
921
|
conn->snd_una += acked;
|
934
|
|
- /* Invoke the acked() callback function */
|
935
|
922
|
conn->tcp_op->acked ( conn, acked );
|
936
|
|
- /* Invoke the senddata() callback function */
|
937
|
|
- tcp_senddata ( conn );
|
938
|
923
|
}
|
939
|
|
-
|
940
|
|
- /* If the connection is in ESTABLISHED and it receives a FIN */
|
941
|
|
- if ( conn->tcp_state == ESTABLISHED && ( tcphdr->flags & TCP_FIN ) ) {
|
942
|
|
- if ( tcphdr->flags & TCP_ACK ) {
|
943
|
|
- tcp_trans ( conn, TCP_LAST_ACK );
|
944
|
|
- goto send_tcp_nomsg;
|
945
|
|
- }
|
946
|
|
- tcp_trans ( conn, TCP_CLOSE_WAIT );
|
947
|
|
-// conn->tcp_op->closed ( conn, CONN_SNDCLOSE );
|
948
|
|
- conn->rcv_nxt++;
|
949
|
|
- if ( ! ( tcphdr->flags & TCP_ACK ) ) {
|
950
|
|
- conn->tcp_flags |= TCP_ACK;
|
951
|
|
- /* Send an acknowledgement */
|
952
|
|
- goto send_tcp_nomsg;
|
|
924
|
+
|
|
925
|
+ /**
|
|
926
|
+ * Check if packet contains new data
|
|
927
|
+ */
|
|
928
|
+ toack = pkb_len ( pkb ) - hlen;
|
|
929
|
+ if ( toack >= 0 ) {
|
|
930
|
+ /* Check the sequence number */
|
|
931
|
+ if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
|
|
932
|
+ conn->rcv_nxt += toack;
|
|
933
|
+ conn->tcp_op->newdata ( conn,
|
|
934
|
+ pkb->data + hlen, toack );
|
|
935
|
+ } else {
|
|
936
|
+ DBG ( "Unexpected sequence number %lx (wanted %lx)\n",
|
|
937
|
+ ntohl ( tcphdr->ack ), conn->rcv_nxt );
|
953
|
938
|
}
|
954
|
|
- /* Otherwise, the packet has been ACKed already */
|
|
939
|
+ conn->tcp_flags |= TCP_ACK;
|
955
|
940
|
}
|
956
|
|
- rc = 0;
|
957
|
|
- goto done;
|
|
941
|
+
|
|
942
|
+ /**
|
|
943
|
+ * Send data
|
|
944
|
+ */
|
|
945
|
+ tcp_senddata ( conn );
|
|
946
|
+ return 0;
|
958
|
947
|
|
959
|
948
|
send_tcp_nomsg:
|
960
|
949
|
free_pkb ( conn->tx_pkb );
|