|  | @@ -559,7 +559,8 @@ static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
 | 
		
	
		
			
			| 559 | 559 |  	return 0;
 | 
		
	
		
			
			| 560 | 560 |  }
 | 
		
	
		
			
			| 561 | 561 |  
 | 
		
	
		
			
			| 562 |  | -/** Handle TCP received FIN
 | 
		
	
		
			
			|  | 562 | +/**
 | 
		
	
		
			
			|  | 563 | + * Handle TCP received FIN
 | 
		
	
		
			
			| 563 | 564 |   *
 | 
		
	
		
			
			| 564 | 565 |   * @v conn		TCP connection
 | 
		
	
		
			
			| 565 | 566 |   * @v seq		SEQ value (in host-endian order)
 | 
		
	
	
		
			
			|  | @@ -587,6 +588,46 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
 | 
		
	
		
			
			| 587 | 588 |  	return 0;
 | 
		
	
		
			
			| 588 | 589 |  }
 | 
		
	
		
			
			| 589 | 590 |  
 | 
		
	
		
			
			|  | 591 | +/**
 | 
		
	
		
			
			|  | 592 | + * Handle TCP received RST
 | 
		
	
		
			
			|  | 593 | + *
 | 
		
	
		
			
			|  | 594 | + * @v conn		TCP connection
 | 
		
	
		
			
			|  | 595 | + * @v seq		SEQ value (in host-endian order)
 | 
		
	
		
			
			|  | 596 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 597 | + */
 | 
		
	
		
			
			|  | 598 | +static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
 | 
		
	
		
			
			|  | 599 | +	struct tcp_application *app = conn->app;
 | 
		
	
		
			
			|  | 600 | +
 | 
		
	
		
			
			|  | 601 | +	/* Accept RST only if it falls within the window.  If we have
 | 
		
	
		
			
			|  | 602 | +	 * not yet received a SYN, then we have no window to test
 | 
		
	
		
			
			|  | 603 | +	 * against, so fall back to checking that our SYN has been
 | 
		
	
		
			
			|  | 604 | +	 * ACKed.
 | 
		
	
		
			
			|  | 605 | +	 */
 | 
		
	
		
			
			|  | 606 | +	if ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
 | 
		
	
		
			
			|  | 607 | +		if ( ( conn->rcv_ack - seq ) > 0 )
 | 
		
	
		
			
			|  | 608 | +			return 0;
 | 
		
	
		
			
			|  | 609 | +	} else {
 | 
		
	
		
			
			|  | 610 | +		if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
 | 
		
	
		
			
			|  | 611 | +			return 0;
 | 
		
	
		
			
			|  | 612 | +	}
 | 
		
	
		
			
			|  | 613 | +
 | 
		
	
		
			
			|  | 614 | +	/* Transition to CLOSED */
 | 
		
	
		
			
			|  | 615 | +	conn->tcp_state = TCP_CLOSED;
 | 
		
	
		
			
			|  | 616 | +	tcp_dump_state ( conn );
 | 
		
	
		
			
			|  | 617 | +
 | 
		
	
		
			
			|  | 618 | +	/* Break association between application and connection */
 | 
		
	
		
			
			|  | 619 | +	tcp_disassociate ( conn );
 | 
		
	
		
			
			|  | 620 | +	
 | 
		
	
		
			
			|  | 621 | +	/* Free the connection */
 | 
		
	
		
			
			|  | 622 | +	free_tcp ( conn );
 | 
		
	
		
			
			|  | 623 | +	
 | 
		
	
		
			
			|  | 624 | +	/* Notify application */
 | 
		
	
		
			
			|  | 625 | +	if ( app && app->tcp_op->closed )
 | 
		
	
		
			
			|  | 626 | +		app->tcp_op->closed ( app, -ECONNRESET );
 | 
		
	
		
			
			|  | 627 | +
 | 
		
	
		
			
			|  | 628 | +	return -ECONNRESET;
 | 
		
	
		
			
			|  | 629 | +}
 | 
		
	
		
			
			|  | 630 | +
 | 
		
	
		
			
			| 590 | 631 |  /**
 | 
		
	
		
			
			| 591 | 632 |   * Process received packet
 | 
		
	
		
			
			| 592 | 633 |   *
 | 
		
	
	
		
			
			|  | @@ -668,13 +709,6 @@ static int tcp_rx ( struct pk_buff *pkb,
 | 
		
	
		
			
			| 668 | 709 |  		goto done;
 | 
		
	
		
			
			| 669 | 710 |  	}
 | 
		
	
		
			
			| 670 | 711 |  
 | 
		
	
		
			
			| 671 |  | -	/* Handle RST, if present */
 | 
		
	
		
			
			| 672 |  | -#warning "Handle RST"
 | 
		
	
		
			
			| 673 |  | -	if ( flags & TCP_RST ) {
 | 
		
	
		
			
			| 674 |  | -		rc = -ECONNRESET;
 | 
		
	
		
			
			| 675 |  | -		goto done;
 | 
		
	
		
			
			| 676 |  | -	}
 | 
		
	
		
			
			| 677 |  | -
 | 
		
	
		
			
			| 678 | 712 |  	/* Handle ACK, if present */
 | 
		
	
		
			
			| 679 | 713 |  	if ( flags & TCP_ACK )
 | 
		
	
		
			
			| 680 | 714 |  		tcp_rx_ack ( conn, ack, win );
 | 
		
	
	
		
			
			|  | @@ -685,6 +719,12 @@ static int tcp_rx ( struct pk_buff *pkb,
 | 
		
	
		
			
			| 685 | 719 |  		seq++;
 | 
		
	
		
			
			| 686 | 720 |  	}
 | 
		
	
		
			
			| 687 | 721 |  
 | 
		
	
		
			
			|  | 722 | +	/* Handle RST, if present */
 | 
		
	
		
			
			|  | 723 | +	if ( flags & TCP_RST ) {
 | 
		
	
		
			
			|  | 724 | +		if ( ( rc = tcp_rx_rst ( conn, seq ) ) != 0 )
 | 
		
	
		
			
			|  | 725 | +			goto done;
 | 
		
	
		
			
			|  | 726 | +	}
 | 
		
	
		
			
			|  | 727 | +
 | 
		
	
		
			
			| 688 | 728 |  	/* Handle new data, if any */
 | 
		
	
		
			
			| 689 | 729 |  	tcp_rx_data ( conn, seq, data, len );
 | 
		
	
		
			
			| 690 | 730 |  	seq += len;
 | 
		
	
	
		
			
			|  | @@ -695,7 +735,7 @@ static int tcp_rx ( struct pk_buff *pkb,
 | 
		
	
		
			
			| 695 | 735 |  		seq++;
 | 
		
	
		
			
			| 696 | 736 |  	}
 | 
		
	
		
			
			| 697 | 737 |  
 | 
		
	
		
			
			| 698 |  | -	/* Dump out any state change as a result of SYN, FIN or ACK */
 | 
		
	
		
			
			|  | 738 | +	/* Dump out any state change as a result of the received packet */
 | 
		
	
		
			
			| 699 | 739 |  	tcp_dump_state ( conn );
 | 
		
	
		
			
			| 700 | 740 |  
 | 
		
	
		
			
			| 701 | 741 |  	/* Send out any pending data.  If peer is expecting an ACK for
 |