Browse Source

Correct some packet ownership and freeing bugs.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
09688cb3b5
1 changed files with 36 additions and 15 deletions
  1. 36
    15
      src/net/tcp.c

+ 36
- 15
src/net/tcp.c View File

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

Loading…
Cancel
Save