Browse Source

Send RST packets when we get a non-matching connection, or receive an

out-of-range ACK.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
b0daa99dce
1 changed files with 51 additions and 9 deletions
  1. 51
    9
      src/net/tcp.c

+ 51
- 9
src/net/tcp.c View File

@@ -425,6 +425,49 @@ static void tcp_expired ( struct retry_timer *timer, int over ) {
425 425
 	}
426 426
 }
427 427
 
428
+/**
429
+ * Send RST response to incoming packet
430
+ *
431
+ * @v in_tcphdr		TCP header of incoming packet
432
+ * @ret rc		Return status code
433
+ */
434
+static int tcp_send_reset ( struct tcp_connection *conn,
435
+			    struct tcp_header *in_tcphdr ) {
436
+	struct pk_buff *pkb;
437
+	struct tcp_header *tcphdr;
438
+
439
+	/* Allocate space for dataless TX buffer */
440
+	pkb = alloc_pkb ( MAX_HDR_LEN );
441
+	if ( ! pkb ) {
442
+		DBGC ( conn, "TCP %p could not allocate data buffer\n", conn );
443
+		return -ENOMEM;
444
+	}
445
+	pkb_reserve ( pkb, MAX_HDR_LEN );
446
+
447
+	/* Construct RST response */
448
+	tcphdr = pkb_push ( pkb, sizeof ( *tcphdr ) );
449
+	memset ( tcphdr, 0, sizeof ( *tcphdr ) );
450
+	tcphdr->src = in_tcphdr->dest;
451
+	tcphdr->dest = in_tcphdr->src;
452
+	tcphdr->seq = in_tcphdr->ack;
453
+	tcphdr->ack = in_tcphdr->seq;
454
+	tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
455
+	tcphdr->flags = ( TCP_RST | TCP_ACK );
456
+	tcphdr->win = htons ( TCP_WINDOW_SIZE );
457
+	tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
458
+
459
+	/* Dump header */
460
+	DBGC ( conn, "TCP %p TX %d->%d %08lx..%08lx           %08lx %4zd",
461
+	       conn, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
462
+	       ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
463
+	       ntohl ( tcphdr->ack ), 0 );
464
+	tcp_dump_flags ( conn, tcphdr->flags );
465
+	DBGC ( conn, "\n" );
466
+
467
+	/* Transmit packet */
468
+	return tcpip_tx ( pkb, &tcp_protocol, &conn->peer, &tcphdr->csum );
469
+}
470
+
428 471
 /**
429 472
  * Identify TCP connection by local port number
430 473
  *
@@ -700,18 +743,20 @@ static int tcp_rx ( struct pk_buff *pkb,
700 743
 	tcp_dump_flags ( conn, tcphdr->flags );
701 744
 	DBGC ( conn, "\n" );
702 745
 
703
-	/* If no connection was found, create dummy connection for
704
-	 * sending RST
705
-	 */
706
-#warning "Handle non-matched connections"
746
+	/* If no connection was found, send RST */
707 747
 	if ( ! conn ) {
748
+		tcp_send_reset ( conn, tcphdr );
708 749
 		rc = -ENOTCONN;
709 750
 		goto done;
710 751
 	}
711 752
 
712 753
 	/* Handle ACK, if present */
713
-	if ( flags & TCP_ACK )
714
-		tcp_rx_ack ( conn, ack, win );
754
+	if ( flags & TCP_ACK ) {
755
+		if ( ( rc = tcp_rx_ack ( conn, ack, win ) ) != 0 ) {
756
+			tcp_send_reset ( conn, tcphdr );
757
+			goto done;
758
+		}
759
+	}
715 760
 
716 761
 	/* Handle SYN, if present */
717 762
 	if ( flags & TCP_SYN ) {
@@ -773,9 +818,6 @@ static int tcp_bind ( struct tcp_connection *conn, uint16_t local_port ) {
773 818
 	struct tcp_connection *existing;
774 819
 	static uint16_t try_port = 1024;
775 820
 
776
-#warning "Fix the port re-use bug"
777
-	try_port = random();
778
-
779 821
 	/* If no port specified, find the first available port */
780 822
 	if ( ! local_port ) {
781 823
 		for ( ; try_port ; try_port++ ) {

Loading…
Cancel
Save