|
@@ -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++ ) {
|