4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP input process routines.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "TcpMain.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check whether the sequence number of the incoming segment is acceptable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seg Pointer to the incoming segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 1 The sequence number is acceptable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The sequence number is not acceptable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpSeqAcceptable (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEG *Seg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (TCP_SEQ_LEQ (Tcb->RcvWl2, Seg->End) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2 + Tcb->RcvWnd));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewReno fast recovery defined in RFC3782.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seg Segment that triggers the fast recovery.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpFastRecover (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEG *Seg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FlightSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Acked;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 1: Three duplicate ACKs and not in fast recovery
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->CongestState != TCP_CONGEST_RECOVER) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 1A: Invoking fast retransmission.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Ssthresh = MAX (FlightSize >> 1, (UINT32) (2 * Tcb->SndMss));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Recover = Tcb->SndNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CongestState = TCP_CONGEST_RECOVER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2: Entering fast retransmission
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpRetransmit (Tcb, Tcb->SndUna);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd = Tcb->Ssthresh + 3 * Tcb->SndMss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastRecover: enter fast retransmission for TCB %p, recover point is %d\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Recover)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // During fast recovery, execute Step 3, 4, 5 of RFC3782
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->Ack == Tcb->SndUna) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 3: Fast Recovery,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If this is a duplicated ACK, increse Cwnd by SMSS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 4 is skipped here only to be executed later
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // by TcpToSendData
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd += Tcb->SndMss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastRecover: received another duplicated ACK (%d) for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Ack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // New data is ACKed, check whether it is a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // full ACK or partial ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GEQ (Seg->Ack, Tcb->Recover)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 5 - Full ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // deflate the congestion window, and exit fast recovery
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd = MIN (Tcb->Ssthresh, FlightSize + Tcb->SndMss);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CongestState = TCP_CONGEST_OPEN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastRecover: received a full ACK(%d) for TCB %p, exit fast recovery\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Ack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 5 - Partial ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // fast retransmit the first unacknowledge field
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // , then deflate the CWnd
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpRetransmit (Tcb, Seg->Ack);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Acked = TCP_SUB_SEQ (Seg->Ack, Tcb->SndUna);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Deflate the CWnd by the amount of new data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ACKed by SEG.ACK. If more than one SMSS data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is ACKed, add back SMSS byte to CWnd after
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Acked >= Tcb->SndMss) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Acked -= Tcb->SndMss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd -= Acked;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastRecover: received a partial ACK(%d) for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Ack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewReno fast loss recovery defined in RFC3792.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seg Segment that triggers the fast loss recovery.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpFastLossRecover (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEG *Seg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // New data is ACKed, check whether it is a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // full ACK or partial ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GEQ (Seg->Ack, Tcb->LossRecover)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Full ACK: exit the loss recovery.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->LossTimes = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CongestState = TCP_CONGEST_OPEN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastLossRecover: received a full ACK(%d) for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Ack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Partial ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // fast retransmit the first unacknowledge field.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpRetransmit (Tcb, Seg->Ack);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpFastLossRecover: received a partial ACK(%d) for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Ack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compute the RTT as specified in RFC2988.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Measure Currently measured RTT in heartbeats.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpComputeRtt (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Measure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INT32 Var;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2.3: Compute the RTO for subsequent RTT measurement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->SRtt != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Var = Tcb->SRtt - (Measure << TCP_RTT_SHIFT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Var < 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Var = -Var;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RttVar = (3 * Tcb->RttVar + Var) >> 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SRtt = 7 * (Tcb->SRtt >> 3) + Measure;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2.2: compute the first RTT measure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SRtt = Measure << TCP_RTT_SHIFT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RttVar = Measure << (TCP_RTT_SHIFT - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Rto = (Tcb->SRtt + MAX (8, 4 * Tcb->RttVar)) >> TCP_RTT_SHIFT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2.4: Limit the RTO to at least 1 second
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Step 2.5: Limit the RTO to a maxium value that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is at least 60 second
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->Rto < TCP_RTO_MIN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Rto = TCP_RTO_MIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Tcb->Rto > TCP_RTO_MAX) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Rto = TCP_RTO_MAX;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpComputeRtt: new RTT for TCB %p computed SRTT: %d RTTVAR: %d RTO: %d\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SRtt,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RttVar,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Rto)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Trim the data; SYN and FIN to fit into the window defined by Left and Right.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf The buffer that contains a received TCP segment without an IP header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Left The sequence number of the window's left edge.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Right The sequence number of the window's right edge.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpTrimSegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Left,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Right
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Drop;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the segment is completely out of window,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // truncate every thing, include SYN and FIN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (Seg->End, Left) || TCP_SEQ_LEQ (Right, Seg->Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq = Seg->End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust the buffer header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seg->Seq, Left)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Drop = TCP_SUB_SEQ (Left, Seg->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Urg = Seg->Seq + Seg->Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq = Left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Drop--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust the urgent point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Urg, Seg->Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Urg = (UINT16) TCP_SUB_SEQ (Urg, Seg->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Drop != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, Drop, NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adjust the buffer tail
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Seg->End, Right)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Drop = TCP_SUB_SEQ (Seg->End, Right);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->End = Right;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Drop--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Drop != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, Drop, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpVerifySegment (Nbuf) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Trim off the data outside the tcb's receive window.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf Pointer to the NET_BUF containing the received tcp segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpTrimInWnd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimSegment (Nbuf, Tcb->RcvNxt, Tcb->RcvWl2 + Tcb->RcvWnd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the data and FIN flag, and check whether to deliver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data to the socket layer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 No error occurred to deliver data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 An error condition occurred. The proper response is to reset the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpDeliverData (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Urgent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // make sure there is some data queued,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and TCP is in a proper state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsListEmpty (&Tcb->RcvQue) || !TCP_CONNECTED (Tcb->State)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Deliver data to the socket layer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = Tcb->RcvQue.ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = Tcb->RcvNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Entry != &Tcb->RcvQue) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpVerifySegment (Nbuf) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Nbuf->Tcp == NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Seg->Seq, Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = Entry->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = Seg->End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvNxt = Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Nbuf->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RFC793 Eighth step: process FIN in sequence
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The peer sends to us junky data after FIN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // reset the connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsListEmpty (&Tcb->RcvQue)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpDeliverData: data received after FIN from peer of TCB %p, reset connection\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpDeliverData: processing FIN from peer of TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Tcb->State) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_SYN_RCVD:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_ESTABLISHED:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_CLOSE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_FIN_WAIT_1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_CLOSING);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // fall through
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_FIN_WAIT_2:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_TIME_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearAllTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->TimeWaitTimeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_CLOSE_WAIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_CLOSING:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_LAST_ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_TIME_WAIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The peer sends to us junk FIN byte. Discard
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the buffer then reset the connection
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->End--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't delay the ack if PUSH flag is on.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_PSH)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf->TotalSize != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Urgent = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvUp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (Seg->End, Tcb->RcvUp)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Urgent = Nbuf->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Urgent = TCP_SUB_SEQ (Tcb->RcvUp, Seg->Seq) + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SockDataRcvd (Tcb->Sk, Nbuf, Urgent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FIN_RCVD (Tcb->State)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SockNoMoreData (Tcb->Sk);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Store the data into the reassemble queue.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf Pointer to the buffer containing the data to be queued.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpQueueData (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Prev;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Cur;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_GET_REF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = &Tcb->RcvQue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fast path to process normal case. That is,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // no out-of-order segments are received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsListEmpty (Head)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (Head, &Nbuf->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the point to insert the buffer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Prev = Head, Cur = Head->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cur != Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Prev = Cur, Cur = Cur->ForwardLink
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether the current segment overlaps with the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // previous segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Prev != Head) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (Seg->End, TCPSEG_NETBUF (Node)->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimSegment (Nbuf, TCPSEG_NETBUF (Node)->End, Seg->End);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (Prev, &Nbuf->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the segments after the insert point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Cur != Head) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->End, Seg->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cur = Cur->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Node->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (TCPSEG_NETBUF (Node)->Seq, Seg->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->Seq, Seg->Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Nbuf->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimSegment (Nbuf, Seg->Seq, TCPSEG_NETBUF (Node)->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cur = Cur->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Adjust the send queue or the retransmit queue.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ack The acknowledge seuqence number of the received segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpAdjustSndQue (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Ack
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Cur;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = &Tcb->SndQue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cur = Head->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Cur != Head) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GEQ (Seg->Seq, Ack)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove completely ACKed segments
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (Seg->End, Ack)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cur = Cur->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Node->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimSegment (Node, Ack, Seg->End);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received TCP segments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf Buffer that contains received a TCP segment without an IP header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Src Source address of the segment, or the peer's IP address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Dst Destination address of the segment, or the local end's IP
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Version IP_VERSION_4 indicates IP4 stack. IP_VERSION_6 indicates
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6 stack.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 Segment processed successfully. It is either accepted or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync discarded. However, no connection is reset by the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 A connection is reset by the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpInput (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Src,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Dst,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Version
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CB *Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CB *Parent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_OPTION Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_HEAD *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Right;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Checksum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Parent = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Head != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = Nbuf->TotalSize - (Head->HeadLen << 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Head->HeadLen < 5) || (Len < 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_INFO, "TcpInput: received an mal-formated packet\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Version == IP_VERSION_4) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Checksum = NetPseudoHeadChecksum (Src->Addr[0], Dst->Addr[0], 6, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Checksum = NetIp6PseudoHeadChecksum (&Src->v6, &Dst->v6, 6, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Checksum = TcpChecksum (Nbuf, Checksum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Checksum != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_ERROR, "TcpInput: received a checksum error packet\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Head->Flag, TCP_FLG_FIN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = TcpLocateTcb (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->DstPort,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dst,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->SrcPort,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Src,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Version,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (BOOLEAN) TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb == NULL) || (Tcb->State == TCP_CLOSED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_INFO, "TcpInput: send reset because no TCB find\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SEND_RESET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TcpFormatNetbuf (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RFC1122 recommended reaction to illegal option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // (in fact, an illegal option length) is reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpParseOption (Nbuf->Tcp, &Option) == -1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: reset the peer because of mal-format option for Tcb %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SEND_RESET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // From now on, the segment is headless
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the segment in LISTEN state.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->State == TCP_LISTEN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First step: Check RST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: discard a reset segment for TCB %p in listening\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Second step: Check ACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Any ACK sent to TCP in LISTEN is reseted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: send reset because of segment with ACK for TCB %p in listening\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SEND_RESET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Third step: Check SYN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // create a child TCB to handle the data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Parent = Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = TcpCloneTcb (Parent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: discard a segment because failed to clone a child for TCB%p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: create a child for TCB %p in listening\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // init the TCB structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, Dst);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, Src);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->LocalEnd.Port = Head->DstPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RemoteEnd.Port = Head->SrcPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpInitTcbLocal (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpInitTcbPeer (Tcb, Seg, &Option);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_SYN_RCVD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimInWnd (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto StepSix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Tcb->State == TCP_SYN_SENT) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First step: Check ACK bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK) && (Seg->Ack != Tcb->Iss + 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: send reset because of wrong ACK received for TCB %p in SYN_SENT\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SEND_RESET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Second step: Check RST bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection reset by peer for TCB %p in SYN_SENT\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DROP_CONNECTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: discard a reset segment because of no ACK for TCB %p in SYN_SENT\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Third step: Check security and precedence. Skipped
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fourth step: Check SYN. Pay attention to sitimulatous open
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpInitTcbPeer (Tcb, Seg, &Option);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndUna = Seg->Ack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Tcb->SndUna, Tcb->Iss)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_ESTABLISHED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpDeliverData (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->CongestState == TCP_CONGEST_OPEN) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpComputeRtt (Tcb, Tcb->RttMeasure);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimInWnd (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection established for TCB %p in SYN_SENT\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto StepSix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Received a SYN segment without ACK, simultanous open.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_SYN_RCVD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Tcb->SndNxt == Tcb->Iss + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpAdjustSndQue (Tcb, Tcb->SndNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimInWnd (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: simultanous open for TCB %p in SYN_SENT\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto StepSix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process segment in SYN_RCVD or TCP_CONNECTED states
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Clear probe timer since the RecvWindow is opened.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->ProbeTimerOn && (Seg->Wnd != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_PROBE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->ProbeTimerOn = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First step: Check whether SEG.SEQ is acceptable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpSeqAcceptable (Tcb, Seg) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: sequence acceptance test failed for segment of TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2)) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->RcvWl2 == Seg->End) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN | TCP_FLG_FIN)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Second step: Check the RST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_WARN, "TcpInput: connection reset for TCB %p\n", Tcb));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->State == TCP_SYN_RCVD) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // This TCB comes from either a LISTEN TCB,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // or active open TCB with simultanous open.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do NOT signal user CONNECTION refused
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if it comes from a LISTEN TCB.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if ((Tcb->State == TCP_ESTABLISHED) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->State == TCP_FIN_WAIT_1) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->State == TCP_FIN_WAIT_2) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->State == TCP_CLOSE_WAIT)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DROP_CONNECTION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Trim the data and flags.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpTrimInWnd (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Third step: Check security and precedence, Ignored
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fourth step: Check the SYN bit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection reset because received extra SYN for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto RESET_THEN_DROP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fifth step: Check the ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: segment discard because of no ACK for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->IpInfo->IpVersion == IP_VERSION_6 && Tcb->Tick == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp6RefreshNeighbor (Tcb, Src, TCP6_KEEP_NEIGHBOR_TIME * TICKS_PER_SECOND);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->State == TCP_SYN_RCVD) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) && TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWnd = Seg->Wnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWl1 = Seg->Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWl2 = Seg->Ack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_ESTABLISHED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpDeliverData (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection established for TCB %p in SYN_RCVD\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Continue the process as ESTABLISHED state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: send reset because of wrong ACK for TCB %p in SYN_RCVD\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SEND_RESET;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: ignore the out-of-data ACK for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto StepSix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: discard segment for future ACK for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto DISCARD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // From now on: SND.UNA <= SEG.ACK <= SND.NXT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // update TsRecent as specified in page 16 RFC1323.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RcvWl2 equals to the variable "LastAckSent"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // defined there.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) && TCP_SEQ_LT (Tcb->RcvWl2, Seg->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->TsRecent = Option.TSVal;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->TsRecentAge = mTcpTick;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpComputeRtt (Tcb, Tcb->RttMeasure);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->Ack == Tcb->SndNxt) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Count duplicate acks.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Seg->Ack == Tcb->SndUna) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->SndUna != Tcb->SndNxt) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Seg->Wnd == Tcb->SndWnd) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (0 == Len)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DupAck++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DupAck = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Congestion avoidance, fast recovery and fast retransmission.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->CongestState == TCP_CONGEST_LOSS)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->CWnd < Tcb->Ssthresh) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd += Tcb->SndMss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd += MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->CWnd = MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->CongestState == TCP_CONGEST_LOSS) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpFastLossRecover (Tcb, Seg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpFastRecover (Tcb, Seg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpAdjustSndQue (Tcb, Seg->Ack);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndUna = Seg->Ack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_LT (Tcb->SndUp, Seg->Ack)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update window info
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Right = Seg->Ack + Seg->Wnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->SndWl1 == Seg->Seq) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Tcb->SndWl2 == Seg->Ack) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Len == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto NO_UPDATE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: peer shrinks the window for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->CongestState == TCP_CONGEST_RECOVER) && (TCP_SEQ_LT (Right, Tcb->Recover))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Recover = Right;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->CongestState == TCP_CONGEST_LOSS) && (TCP_SEQ_LT (Right, Tcb->LossRecover))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->LossRecover = Right;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Right, Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndNxt = Right;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Right == Tcb->SndUna) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetProbeTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWnd = Seg->Wnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWl1 = Seg->Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndWl2 = Seg->Ack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNO_UPDATE:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) && (Tcb->SndUna == Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: local FIN is ACKed by peer for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transit the state if proper.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Tcb->State) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_FIN_WAIT_1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_FIN_WAIT_2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearAllTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_FIN_WAIT_2:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_CLOSE_WAIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_CLOSING:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_TIME_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClearAllTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->TimeWaitTimeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_LAST_ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetState (Tcb, TCP_CLOSED);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case TCP_TIME_WAIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->TimeWaitTimeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sixth step: Check the URG bit.update the Urg point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if in TCP_CAN_RECV, otherwise, leave the RcvUp intact.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncStepSix:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Idle = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetKeepaliveTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) && !TCP_FIN_RCVD (Tcb->State)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: received urgent data from peer for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Urg = Seg->Seq + Seg->Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) && TCP_SEQ_GT (Urg, Tcb->RcvUp)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvUp = Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvUp = Urg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Seventh step: Process the segment data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->End != Seg->Seq) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FIN_RCVD (Tcb->State)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection reset because data is lost for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto RESET_THEN_DROP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpInput: connection reset because data is lost for connected TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto RESET_THEN_DROP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpQueueData (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpDeliverData (Tcb) == -1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto RESET_THEN_DROP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsListEmpty (&Tcb->RcvQue)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Eighth step: check the FIN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // This step is moved to TcpDeliverData. FIN will be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // processed in sequence there. Check the comments in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the beginning of the file header for information.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Tcb is a new child of the listening Parent,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // commit it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Parent != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->Parent = Parent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpInsertTcb (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->State != TCP_CLOSED) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (TcpToSendData (Tcb, 0) == 0) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Nbuf->TotalSize != 0))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpToSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRESET_THEN_DROP:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendReset (Tcb, Head, Len, Dst, Src, Version);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDROP_CONNECTION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSEND_RESET:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendReset (Tcb, Head, Len, Dst, Src, Version);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDISCARD:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Tcb is a child of Parent, and it doesn't survive
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG ((EFI_D_WARN, "TcpInput: Discard a packet\n"));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Parent != NULL) && (Tcb != NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Tcb->Sk != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received ICMP error messages for TCP.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf The buffer that contains part of the TCP segment without an IP header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync truncated from the ICMP error packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IcmpErr The ICMP error code interpreted from an ICMP error packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Src Source address of the ICMP error message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Dst Destination address of the ICMP error message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Version IP_VERSION_4 indicates IP4 stack. IP_VERSION_6 indicates
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6 stack.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpIcmpInput (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 IcmpErr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Src,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Dst,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Version
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_HEAD *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CB *Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS IcmpErrStatus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IcmpErrIsHard;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IcmpErrNotify;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Head != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = TcpLocateTcb (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->DstPort,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dst,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->SrcPort,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Src,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Version,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb == NULL || Tcb->State == TCP_CLOSED) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto CLEAN_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the sequence number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = NTOHL (Head->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto CLEAN_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpErrStatus = IpIoGetIcmpErrStatus (IcmpErr, Tcb->Sk->IpVersion, &IcmpErrIsHard, &IcmpErrNotify);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IcmpErrNotify) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCK_ERROR (Tcb->Sk, IcmpErrStatus);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IcmpErrIsHard) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpClose (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCLEAN_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}