|
@@ -636,9 +636,13 @@ int tcp_senddata ( struct tcp_connection *conn ) {
|
636
|
636
|
*/
|
637
|
637
|
int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
|
638
|
638
|
struct sockaddr_tcpip *peer = &conn->peer;
|
639
|
|
- struct pk_buff *pkb = conn->tx_pkb;
|
|
639
|
+ struct pk_buff *pkb;
|
640
|
640
|
int slen;
|
641
|
641
|
|
|
642
|
+ /* Take ownership of the TX buffer from the connection */
|
|
643
|
+ pkb = conn->tx_pkb;
|
|
644
|
+ conn->tx_pkb = NULL;
|
|
645
|
+
|
642
|
646
|
/* Determine the amount of data to be sent */
|
643
|
647
|
slen = len < conn->snd_win ? len : conn->snd_win;
|
644
|
648
|
/* Copy payload */
|
|
@@ -694,11 +698,13 @@ static int tcp_rx ( struct pk_buff *pkb,
|
694
|
698
|
struct tcp_header *tcphdr;
|
695
|
699
|
uint32_t acked, toack;
|
696
|
700
|
int hlen;
|
|
701
|
+ int rc;
|
697
|
702
|
|
698
|
703
|
/* Sanity check */
|
699
|
704
|
if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
|
700
|
705
|
DBG ( "Packet too short (%d bytes)\n", pkb_len ( pkb ) );
|
701
|
|
- return -EINVAL;
|
|
706
|
+ rc = -EINVAL;
|
|
707
|
+ goto done;
|
702
|
708
|
}
|
703
|
709
|
|
704
|
710
|
|
|
@@ -713,7 +719,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
713
|
719
|
DBG ( "TCP options sent\n" );
|
714
|
720
|
} else {
|
715
|
721
|
DBG ( "Bad header length (%d bytes)\n", hlen );
|
716
|
|
- return -EINVAL;
|
|
722
|
+ rc = -EINVAL;
|
|
723
|
+ goto done;
|
717
|
724
|
}
|
718
|
725
|
}
|
719
|
726
|
|
|
@@ -728,7 +735,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
728
|
735
|
}
|
729
|
736
|
|
730
|
737
|
DBG ( "No connection found on port %d\n", ntohs ( tcphdr->dest ) );
|
731
|
|
- return 0;
|
|
738
|
+ rc = 0;
|
|
739
|
+ goto done;
|
732
|
740
|
|
733
|
741
|
found_conn:
|
734
|
742
|
/* Stop the timer */
|
|
@@ -743,7 +751,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
743
|
751
|
case TCP_CLOSED:
|
744
|
752
|
DBG ( "tcp_rx(): Invalid state %s\n",
|
745
|
753
|
tcp_states[conn->tcp_state] );
|
746
|
|
- return -EINVAL;
|
|
754
|
+ rc = -EINVAL;
|
|
755
|
+ goto done;
|
747
|
756
|
case TCP_LISTEN:
|
748
|
757
|
if ( tcphdr->flags & TCP_SYN ) {
|
749
|
758
|
tcp_trans ( conn, TCP_SYN_RCVD );
|
|
@@ -776,7 +785,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
776
|
785
|
conn->tcp_op->connected ( conn );
|
777
|
786
|
conn->tcp_flags |= TCP_ACK;
|
778
|
787
|
tcp_senddata ( conn );
|
779
|
|
- return;
|
|
788
|
+ rc = 0;
|
|
789
|
+ goto done;
|
780
|
790
|
} else {
|
781
|
791
|
tcp_trans ( conn, TCP_SYN_RCVD );
|
782
|
792
|
conn->tcp_flags |= TCP_SYN;
|
|
@@ -789,7 +799,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
789
|
799
|
if ( tcphdr->flags & TCP_RST ) {
|
790
|
800
|
tcp_trans ( conn, TCP_LISTEN );
|
791
|
801
|
conn->tcp_op->closed ( conn, CONN_RESTART );
|
792
|
|
- return 0;
|
|
802
|
+ rc = 0;
|
|
803
|
+ goto done;
|
793
|
804
|
}
|
794
|
805
|
if ( tcphdr->flags & TCP_ACK ) {
|
795
|
806
|
tcp_trans ( conn, TCP_ESTABLISHED );
|
|
@@ -799,7 +810,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
799
|
810
|
*/
|
800
|
811
|
conn->snd_una = tcphdr->ack - 1;
|
801
|
812
|
conn->tcp_op->connected ( conn );
|
802
|
|
- return 0;
|
|
813
|
+ rc = 0;
|
|
814
|
+ goto done;
|
803
|
815
|
}
|
804
|
816
|
/* Unexpected packet */
|
805
|
817
|
goto unexpected;
|
|
@@ -849,7 +861,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
849
|
861
|
if ( tcphdr->flags & TCP_ACK ) {
|
850
|
862
|
tcp_trans ( conn, TCP_TIME_WAIT );
|
851
|
863
|
start_timer ( &conn->timer );
|
852
|
|
- return 0;
|
|
864
|
+ rc = 0;
|
|
865
|
+ goto done;
|
853
|
866
|
}
|
854
|
867
|
/* Unexpected packet */
|
855
|
868
|
goto unexpected;
|
|
@@ -862,7 +875,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
862
|
875
|
case TCP_LAST_ACK:
|
863
|
876
|
if ( tcphdr->flags & TCP_ACK ) {
|
864
|
877
|
tcp_trans ( conn, TCP_CLOSED );
|
865
|
|
- return 0;
|
|
878
|
+ rc = 0;
|
|
879
|
+ goto done;
|
866
|
880
|
}
|
867
|
881
|
/* Unexpected packet */
|
868
|
882
|
goto unexpected;
|
|
@@ -900,7 +914,8 @@ static int tcp_rx ( struct pk_buff *pkb,
|
900
|
914
|
acked = ntohl ( tcphdr->ack ) - conn->snd_una;
|
901
|
915
|
if ( acked < 0 ) { /* TODO: Replace all uint32_t arith */
|
902
|
916
|
DBG ( "Previously ACKed (%d)\n", tcphdr->ack );
|
903
|
|
- return 0;
|
|
917
|
+ rc = 0;
|
|
918
|
+ goto done;
|
904
|
919
|
}
|
905
|
920
|
/* Advance snd stream */
|
906
|
921
|
conn->snd_una += acked;
|
|
@@ -922,24 +937,30 @@ static int tcp_rx ( struct pk_buff *pkb,
|
922
|
937
|
}
|
923
|
938
|
/* Otherwise, the packet has been ACKed already */
|
924
|
939
|
}
|
925
|
|
- return 0;
|
|
940
|
+ rc = 0;
|
|
941
|
+ goto done;
|
926
|
942
|
|
927
|
943
|
send_tcp_nomsg:
|
928
|
944
|
free_pkb ( conn->tx_pkb );
|
929
|
945
|
conn->tx_pkb = alloc_pkb ( MIN_PKB_LEN );
|
930
|
946
|
pkb_reserve ( conn->tx_pkb, MAX_HDR_LEN );
|
931
|
|
- int rc;
|
932
|
947
|
if ( ( rc = tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN ) ) != 0 ) {
|
933
|
948
|
DBG ( "Error sending TCP message (rc = %d)\n", rc );
|
934
|
949
|
}
|
935
|
|
- return 0;
|
|
950
|
+ goto done;
|
936
|
951
|
|
937
|
952
|
unexpected:
|
938
|
953
|
DBG ( "Unexpected packet received in %s with flags = %#hx\n",
|
939
|
954
|
tcp_states[conn->tcp_state], tcphdr->flags & TCP_MASK_FLAGS );
|
940
|
955
|
tcp_close ( conn );
|
941
|
956
|
free_pkb ( conn->tx_pkb );
|
942
|
|
- return -EINVAL;
|
|
957
|
+ conn->tx_pkb = NULL;
|
|
958
|
+ rc = -EINVAL;
|
|
959
|
+ goto done;
|
|
960
|
+
|
|
961
|
+ done:
|
|
962
|
+ free_pkb ( pkb );
|
|
963
|
+ return rc;
|
943
|
964
|
}
|
944
|
965
|
|
945
|
966
|
/** TCP protocol */
|