Home | History | Annotate | Download | only in Tcp4Dxe
      1 /** @file
      2   TCP input process routines.
      3 
      4 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php<BR>
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 
     16 #include "Tcp4Main.h"
     17 
     18 
     19 /**
     20   Check whether the sequence number of the incoming segment is acceptable.
     21 
     22   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
     23   @param  Seg      Pointer to the incoming segment.
     24 
     25   @retval 1       The sequence number is acceptable.
     26   @retval 0       The sequence number is not acceptable.
     27 
     28 **/
     29 INTN
     30 TcpSeqAcceptable (
     31   IN TCP_CB  *Tcb,
     32   IN TCP_SEG *Seg
     33   )
     34 {
     35   return (TCP_SEQ_LEQ (Tcb->RcvWl2, Seg->End) &&
     36           TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2 + Tcb->RcvWnd));
     37 }
     38 
     39 
     40 /**
     41   NewReno fast recovery, RFC3782.
     42 
     43   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
     44   @param  Seg      Segment that triggers the fast recovery.
     45 
     46 **/
     47 VOID
     48 TcpFastRecover (
     49   IN OUT TCP_CB  *Tcb,
     50   IN     TCP_SEG *Seg
     51   )
     52 {
     53   UINT32  FlightSize;
     54   UINT32  Acked;
     55 
     56   //
     57   // Step 1: Three duplicate ACKs and not in fast recovery
     58   //
     59   if (Tcb->CongestState != TCP_CONGEST_RECOVER) {
     60 
     61     //
     62     // Step 1A: Invoking fast retransmission.
     63     //
     64     FlightSize        = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
     65 
     66     Tcb->Ssthresh     = MAX (FlightSize >> 1, (UINT32) (2 * Tcb->SndMss));
     67     Tcb->Recover      = Tcb->SndNxt;
     68 
     69     Tcb->CongestState = TCP_CONGEST_RECOVER;
     70     TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
     71 
     72     //
     73     // Step 2: Entering fast retransmission
     74     //
     75     TcpRetransmit (Tcb, Tcb->SndUna);
     76     Tcb->CWnd = Tcb->Ssthresh + 3 * Tcb->SndMss;
     77 
     78     DEBUG ((EFI_D_INFO, "TcpFastRecover: enter fast retransmission"
     79       " for TCB %p, recover point is %d\n", Tcb, Tcb->Recover));
     80     return;
     81   }
     82 
     83   //
     84   // During fast recovery, execute Step 3, 4, 5 of RFC3782
     85   //
     86   if (Seg->Ack == Tcb->SndUna) {
     87 
     88     //
     89     // Step 3: Fast Recovery,
     90     // If this is a duplicated ACK, increse Cwnd by SMSS.
     91     //
     92 
     93     // Step 4 is skipped here only to be executed later
     94     // by TcpToSendData
     95     //
     96     Tcb->CWnd += Tcb->SndMss;
     97     DEBUG ((EFI_D_INFO, "TcpFastRecover: received another"
     98       " duplicated ACK (%d) for TCB %p\n", Seg->Ack, Tcb));
     99 
    100   } else {
    101 
    102     //
    103     // New data is ACKed, check whether it is a
    104     // full ACK or partial ACK
    105     //
    106     if (TCP_SEQ_GEQ (Seg->Ack, Tcb->Recover)) {
    107 
    108       //
    109       // Step 5 - Full ACK:
    110       // deflate the congestion window, and exit fast recovery
    111       //
    112       FlightSize        = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
    113 
    114       Tcb->CWnd         = MIN (Tcb->Ssthresh, FlightSize + Tcb->SndMss);
    115 
    116       Tcb->CongestState = TCP_CONGEST_OPEN;
    117       DEBUG ((EFI_D_INFO, "TcpFastRecover: received a full ACK(%d)"
    118         " for TCB %p, exit fast recovery\n", Seg->Ack, Tcb));
    119 
    120     } else {
    121 
    122       //
    123       // Step 5 - Partial ACK:
    124       // fast retransmit the first unacknowledge field
    125       // , then deflate the CWnd
    126       //
    127       TcpRetransmit (Tcb, Seg->Ack);
    128       Acked = TCP_SUB_SEQ (Seg->Ack, Tcb->SndUna);
    129 
    130       //
    131       // Deflate the CWnd by the amount of new data
    132       // ACKed by SEG.ACK. If more than one SMSS data
    133       // is ACKed, add back SMSS byte to CWnd after
    134       //
    135       if (Acked >= Tcb->SndMss) {
    136         Acked -= Tcb->SndMss;
    137 
    138       }
    139 
    140       Tcb->CWnd -= Acked;
    141 
    142       DEBUG ((EFI_D_INFO, "TcpFastRecover: received a partial"
    143         " ACK(%d) for TCB %p\n", Seg->Ack, Tcb));
    144 
    145     }
    146   }
    147 }
    148 
    149 
    150 /**
    151   NewReno fast loss recovery, RFC3792.
    152 
    153   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    154   @param  Seg      Segment that triggers the fast loss recovery.
    155 
    156 **/
    157 VOID
    158 TcpFastLossRecover (
    159   IN OUT TCP_CB  *Tcb,
    160   IN     TCP_SEG *Seg
    161   )
    162 {
    163   if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
    164 
    165     //
    166     // New data is ACKed, check whether it is a
    167     // full ACK or partial ACK
    168     //
    169     if (TCP_SEQ_GEQ (Seg->Ack, Tcb->LossRecover)) {
    170 
    171       //
    172       // Full ACK: exit the loss recovery.
    173       //
    174       Tcb->LossTimes    = 0;
    175       Tcb->CongestState = TCP_CONGEST_OPEN;
    176 
    177       DEBUG ((EFI_D_INFO, "TcpFastLossRecover: received a "
    178         "full ACK(%d) for TCB %p\n", Seg->Ack, Tcb));
    179 
    180     } else {
    181 
    182       //
    183       // Partial ACK:
    184       // fast retransmit the first unacknowledge field.
    185       //
    186       TcpRetransmit (Tcb, Seg->Ack);
    187       DEBUG ((EFI_D_INFO, "TcpFastLossRecover: received a "
    188         "partial ACK(%d) for TCB %p\n", Seg->Ack, Tcb));
    189     }
    190   }
    191 }
    192 
    193 
    194 /**
    195   Compute the RTT as specified in RFC2988.
    196 
    197   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    198   @param  Measure  Currently measured RTT in heart beats.
    199 
    200 **/
    201 VOID
    202 TcpComputeRtt (
    203   IN OUT TCP_CB *Tcb,
    204   IN     UINT32 Measure
    205   )
    206 {
    207   INT32 Var;
    208 
    209   //
    210   // Step 2.3: Compute the RTO for subsequent RTT measurement.
    211   //
    212   if (Tcb->SRtt != 0) {
    213 
    214     Var = Tcb->SRtt - (Measure << TCP_RTT_SHIFT);
    215 
    216     if (Var < 0) {
    217       Var = -Var;
    218     }
    219 
    220     Tcb->RttVar = (3 * Tcb->RttVar + Var) >> 2;
    221     Tcb->SRtt   = 7 * (Tcb->SRtt >> 3) + Measure;
    222 
    223   } else {
    224     //
    225     // Step 2.2: compute the first RTT measure
    226     //
    227     Tcb->SRtt   = Measure << TCP_RTT_SHIFT;
    228     Tcb->RttVar = Measure << (TCP_RTT_SHIFT - 1);
    229   }
    230 
    231   Tcb->Rto = (Tcb->SRtt + MAX (8, 4 * Tcb->RttVar)) >> TCP_RTT_SHIFT;
    232 
    233   //
    234   // Step 2.4: Limit the RTO to at least 1 second
    235   // Step 2.5: Limit the RTO to a maxium value that
    236   // is at least 60 second
    237   //
    238   if (Tcb->Rto < TCP_RTO_MIN) {
    239     Tcb->Rto = TCP_RTO_MIN;
    240 
    241   } else if (Tcb->Rto > TCP_RTO_MAX) {
    242     Tcb->Rto = TCP_RTO_MAX;
    243 
    244   }
    245 
    246   DEBUG ((EFI_D_INFO, "TcpComputeRtt: new RTT for TCB %p"
    247     " computed SRTT: %d RTTVAR: %d RTO: %d\n",
    248     Tcb, Tcb->SRtt, Tcb->RttVar, Tcb->Rto));
    249 
    250 }
    251 
    252 
    253 /**
    254   Trim the data, SYN and FIN to fit into the window defined by Left and Right.
    255 
    256   @param  Nbuf     Buffer that contains received TCP segment without IP header.
    257   @param  Left     The sequence number of the window's left edge.
    258   @param  Right    The sequence number of the window's right edge.
    259 
    260 **/
    261 VOID
    262 TcpTrimSegment (
    263   IN NET_BUF   *Nbuf,
    264   IN TCP_SEQNO Left,
    265   IN TCP_SEQNO Right
    266   )
    267 {
    268   TCP_SEG   *Seg;
    269   TCP_SEQNO Urg;
    270   UINT32    Drop;
    271 
    272   Seg = TCPSEG_NETBUF (Nbuf);
    273 
    274   //
    275   // If the segment is completely out of window,
    276   // truncate every thing, include SYN and FIN.
    277   //
    278   if (TCP_SEQ_LEQ (Seg->End, Left) || TCP_SEQ_LEQ (Right, Seg->Seq)) {
    279 
    280     TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);
    281     TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);
    282 
    283     Seg->Seq = Seg->End;
    284     NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_HEAD);
    285     return;
    286   }
    287 
    288   //
    289   // Adjust the buffer header
    290   //
    291   if (TCP_SEQ_LT (Seg->Seq, Left)) {
    292 
    293     Drop      = TCP_SUB_SEQ (Left, Seg->Seq);
    294     Urg       = Seg->Seq + Seg->Urg;
    295     Seg->Seq  = Left;
    296 
    297     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
    298       TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);
    299       Drop--;
    300     }
    301 
    302     //
    303     // Adjust the urgent point
    304     //
    305     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG)) {
    306 
    307       if (TCP_SEQ_LT (Urg, Seg->Seq)) {
    308 
    309         TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);
    310       } else {
    311         Seg->Urg = (UINT16) TCP_SUB_SEQ (Urg, Seg->Seq);
    312       }
    313     }
    314 
    315     if (Drop != 0) {
    316       NetbufTrim (Nbuf, Drop, NET_BUF_HEAD);
    317     }
    318   }
    319 
    320   //
    321   // Adjust the buffer tail
    322   //
    323   if (TCP_SEQ_GT (Seg->End, Right)) {
    324 
    325     Drop      = TCP_SUB_SEQ (Seg->End, Right);
    326     Seg->End  = Right;
    327 
    328     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
    329       TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);
    330       Drop--;
    331     }
    332 
    333     if (Drop != 0) {
    334       NetbufTrim (Nbuf, Drop, NET_BUF_TAIL);
    335     }
    336   }
    337 
    338   ASSERT (TcpVerifySegment (Nbuf) != 0);
    339 }
    340 
    341 
    342 /**
    343   Trim off the data outside the tcb's receive window.
    344 
    345   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    346   @param  Nbuf     Pointer to the NET_BUF containing the received tcp segment.
    347 
    348 **/
    349 VOID
    350 TcpTrimInWnd (
    351   IN TCP_CB  *Tcb,
    352   IN NET_BUF *Nbuf
    353   )
    354 {
    355   TcpTrimSegment (Nbuf, Tcb->RcvNxt, Tcb->RcvWl2 + Tcb->RcvWnd);
    356 }
    357 
    358 
    359 /**
    360   Process the data and FIN flag, check whether to deliver
    361   data to the socket layer.
    362 
    363   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    364 
    365   @retval 0        No error occurred to deliver data.
    366   @retval -1       Error condition occurred. Proper response is to reset the
    367                    connection.
    368 
    369 **/
    370 INTN
    371 TcpDeliverData (
    372   IN OUT TCP_CB *Tcb
    373   )
    374 {
    375   LIST_ENTRY      *Entry;
    376   NET_BUF         *Nbuf;
    377   TCP_SEQNO       Seq;
    378   TCP_SEG         *Seg;
    379   UINT32          Urgent;
    380 
    381   ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
    382 
    383   //
    384   // make sure there is some data queued,
    385   // and TCP is in a proper state
    386   //
    387   if (IsListEmpty (&Tcb->RcvQue) || !TCP_CONNECTED (Tcb->State)) {
    388 
    389     return 0;
    390   }
    391 
    392   //
    393   // Deliver data to the socket layer
    394   //
    395   Entry = Tcb->RcvQue.ForwardLink;
    396   Seq   = Tcb->RcvNxt;
    397 
    398   while (Entry != &Tcb->RcvQue) {
    399     Nbuf  = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
    400     Seg   = TCPSEG_NETBUF (Nbuf);
    401 
    402     ASSERT (TcpVerifySegment (Nbuf) != 0);
    403     ASSERT (Nbuf->Tcp == NULL);
    404 
    405     if (TCP_SEQ_GT (Seg->Seq, Seq)) {
    406       break;
    407     }
    408 
    409     Entry       = Entry->ForwardLink;
    410     Seq         = Seg->End;
    411     Tcb->RcvNxt = Seq;
    412 
    413     RemoveEntryList (&Nbuf->List);
    414 
    415     //
    416     // RFC793 Eighth step: process FIN in sequence
    417     //
    418     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
    419 
    420       //
    421       // The peer sends to us junky data after FIN,
    422       // reset the connection.
    423       //
    424       if (!IsListEmpty (&Tcb->RcvQue)) {
    425         DEBUG ((EFI_D_ERROR, "TcpDeliverData: data received after"
    426           " FIN from peer of TCB %p, reset connection\n", Tcb));
    427 
    428         NetbufFree (Nbuf);
    429         return -1;
    430       }
    431 
    432       DEBUG ((EFI_D_INFO, "TcpDeliverData: processing FIN "
    433         "from peer of TCB %p\n", Tcb));
    434 
    435       switch (Tcb->State) {
    436       case TCP_SYN_RCVD:
    437       case TCP_ESTABLISHED:
    438 
    439         TcpSetState (Tcb, TCP_CLOSE_WAIT);
    440         break;
    441 
    442       case TCP_FIN_WAIT_1:
    443 
    444         if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
    445 
    446           TcpSetState (Tcb, TCP_CLOSING);
    447           break;
    448         }
    449 
    450       //
    451       // fall through
    452       //
    453       case TCP_FIN_WAIT_2:
    454 
    455         TcpSetState (Tcb, TCP_TIME_WAIT);
    456         TcpClearAllTimer (Tcb);
    457 
    458         if (Tcb->TimeWaitTimeout != 0) {
    459 
    460           TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
    461         } else {
    462 
    463           DEBUG ((EFI_D_WARN, "Connection closed immediately "
    464             "because app disables TIME_WAIT timer for %p\n", Tcb));
    465 
    466           TcpSendAck (Tcb);
    467           TcpClose (Tcb);
    468         }
    469         break;
    470 
    471       case TCP_CLOSE_WAIT:
    472       case TCP_CLOSING:
    473       case TCP_LAST_ACK:
    474       case TCP_TIME_WAIT:
    475         //
    476         // The peer sends to us junk FIN byte. Discard
    477         // the buffer then reset the connection
    478         //
    479         NetbufFree (Nbuf);
    480         return -1;
    481       default:
    482         break;
    483       }
    484 
    485       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
    486 
    487       Seg->End--;
    488     }
    489 
    490     //
    491     // Don't delay the ack if PUSH flag is on.
    492     //
    493     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_PSH)) {
    494 
    495       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
    496     }
    497 
    498     if (Nbuf->TotalSize != 0) {
    499       Urgent = 0;
    500 
    501       if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&
    502           TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvUp)) {
    503 
    504         if (TCP_SEQ_LEQ (Seg->End, Tcb->RcvUp)) {
    505           Urgent = Nbuf->TotalSize;
    506         } else {
    507           Urgent = TCP_SUB_SEQ (Tcb->RcvUp, Seg->Seq) + 1;
    508         }
    509       }
    510 
    511       SockDataRcvd (Tcb->Sk, Nbuf, Urgent);
    512     }
    513 
    514     if (TCP_FIN_RCVD (Tcb->State)) {
    515 
    516       SockNoMoreData (Tcb->Sk);
    517     }
    518 
    519     NetbufFree (Nbuf);
    520   }
    521 
    522   return 0;
    523 }
    524 
    525 
    526 /**
    527   Store the data into the reassemble queue.
    528 
    529   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    530   @param  Nbuf     Pointer to the buffer containing the data to be queued.
    531 
    532 **/
    533 VOID
    534 TcpQueueData (
    535   IN OUT TCP_CB  *Tcb,
    536   IN     NET_BUF *Nbuf
    537   )
    538 {
    539   TCP_SEG         *Seg;
    540   LIST_ENTRY      *Head;
    541   LIST_ENTRY      *Prev;
    542   LIST_ENTRY      *Cur;
    543   NET_BUF         *Node;
    544 
    545   ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
    546 
    547   NET_GET_REF (Nbuf);
    548 
    549   Seg   = TCPSEG_NETBUF (Nbuf);
    550   Head  = &Tcb->RcvQue;
    551 
    552   //
    553   // Fast path to process normal case. That is,
    554   // no out-of-order segments are received.
    555   //
    556   if (IsListEmpty (Head)) {
    557 
    558     InsertTailList (Head, &Nbuf->List);
    559     return;
    560   }
    561 
    562   //
    563   // Find the point to insert the buffer
    564   //
    565   for (Prev = Head, Cur = Head->ForwardLink;
    566        Cur != Head;
    567        Prev = Cur, Cur = Cur->ForwardLink) {
    568 
    569     Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    570 
    571     if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->Seq)) {
    572       break;
    573     }
    574   }
    575 
    576   //
    577   // Check whether the current segment overlaps with the
    578   // previous segment.
    579   //
    580   if (Prev != Head) {
    581     Node = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);
    582 
    583     if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->End)) {
    584 
    585       if (TCP_SEQ_LEQ (Seg->End, TCPSEG_NETBUF (Node)->End)) {
    586 
    587         NetbufFree (Nbuf);
    588         return;
    589       }
    590 
    591       TcpTrimSegment (Nbuf, TCPSEG_NETBUF (Node)->End, Seg->End);
    592     }
    593   }
    594 
    595   InsertHeadList (Prev, &Nbuf->List);
    596 
    597   TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
    598 
    599   //
    600   // Check the segments after the insert point.
    601   //
    602   while (Cur != Head) {
    603     Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    604 
    605     if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->End, Seg->End)) {
    606 
    607       Cur = Cur->ForwardLink;
    608 
    609       RemoveEntryList (&Node->List);
    610       NetbufFree (Node);
    611       continue;
    612     }
    613 
    614     if (TCP_SEQ_LT (TCPSEG_NETBUF (Node)->Seq, Seg->End)) {
    615 
    616       if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->Seq, Seg->Seq)) {
    617 
    618         RemoveEntryList (&Nbuf->List);
    619         NetbufFree (Nbuf);
    620         return ;
    621       }
    622 
    623       TcpTrimSegment (Nbuf, Seg->Seq, TCPSEG_NETBUF (Node)->Seq);
    624       break;
    625     }
    626 
    627     Cur = Cur->ForwardLink;
    628   }
    629 }
    630 
    631 
    632 /**
    633   Ajust the send queue or the retransmit queue.
    634 
    635   @param  Tcb      Pointer to the TCP_CB of this TCP instance.
    636   @param  Ack      The acknowledge seuqence number of the received segment.
    637 
    638 **/
    639 VOID
    640 TcpAdjustSndQue (
    641   IN TCP_CB    *Tcb,
    642   IN TCP_SEQNO Ack
    643   )
    644 {
    645   LIST_ENTRY      *Head;
    646   LIST_ENTRY      *Cur;
    647   NET_BUF         *Node;
    648   TCP_SEG         *Seg;
    649 
    650   Head  = &Tcb->SndQue;
    651   Cur   = Head->ForwardLink;
    652 
    653   while (Cur != Head) {
    654     Node  = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
    655     Seg   = TCPSEG_NETBUF (Node);
    656 
    657     if (TCP_SEQ_GEQ (Seg->Seq, Ack)) {
    658       break;
    659     }
    660 
    661     //
    662     // Remove completely ACKed segments
    663     //
    664     if (TCP_SEQ_LEQ (Seg->End, Ack)) {
    665       Cur = Cur->ForwardLink;
    666 
    667       RemoveEntryList (&Node->List);
    668       NetbufFree (Node);
    669       continue;
    670     }
    671 
    672     TcpTrimSegment (Node, Ack, Seg->End);
    673     break;
    674   }
    675 }
    676 
    677 
    678 /**
    679   Process the received TCP segments.
    680 
    681   @param  Nbuf     Buffer that contains received TCP segment without IP header.
    682   @param  Src      Source address of the segment, or the peer's IP address.
    683   @param  Dst      Destination address of the segment, or the local end's IP
    684                    address.
    685 
    686   @retval 0        Segment is processed successfully. It is either accepted or
    687                    discarded. But no connection is reset by the segment.
    688   @retval -1       A connection is reset by the segment.
    689 
    690 **/
    691 INTN
    692 TcpInput (
    693   IN NET_BUF *Nbuf,
    694   IN UINT32  Src,
    695   IN UINT32  Dst
    696   )
    697 {
    698   TCP_CB      *Tcb;
    699   TCP_CB      *Parent;
    700   TCP_OPTION  Option;
    701   TCP_HEAD    *Head;
    702   INT32       Len;
    703   TCP_SEG     *Seg;
    704   TCP_SEQNO   Right;
    705   TCP_SEQNO   Urg;
    706 
    707   NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
    708 
    709   Parent  = NULL;
    710   Tcb     = NULL;
    711 
    712   Head    = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
    713   ASSERT (Head != NULL);
    714   Len     = Nbuf->TotalSize - (Head->HeadLen << 2);
    715 
    716   if ((Head->HeadLen < 5) || (Len < 0) ||
    717       (TcpChecksum (Nbuf, NetPseudoHeadChecksum (Src, Dst, 6, 0)) != 0)) {
    718 
    719     DEBUG ((EFI_D_INFO, "TcpInput: received an mal-formated packet\n"));
    720     goto DISCARD;
    721   }
    722 
    723   if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) {
    724     Len++;
    725   }
    726 
    727   if (TCP_FLG_ON (Head->Flag, TCP_FLG_FIN)) {
    728     Len++;
    729   }
    730 
    731   Tcb = TcpLocateTcb (
    732           Head->DstPort,
    733           Dst,
    734           Head->SrcPort,
    735           Src,
    736           (BOOLEAN) TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)
    737           );
    738 
    739   if ((Tcb == NULL) || (Tcb->State == TCP_CLOSED)) {
    740     DEBUG ((EFI_D_INFO, "TcpInput: send reset because no TCB found\n"));
    741 
    742     Tcb = NULL;
    743     goto SEND_RESET;
    744   }
    745 
    746   Seg = TcpFormatNetbuf (Tcb, Nbuf);
    747 
    748   //
    749   // RFC1122 recommended reaction to illegal option
    750   // (in fact, an illegal option length) is reset.
    751   //
    752   if (TcpParseOption (Nbuf->Tcp, &Option) == -1) {
    753     DEBUG ((EFI_D_ERROR, "TcpInput: reset the peer because"
    754       " of malformed option for TCB %p\n", Tcb));
    755 
    756     goto SEND_RESET;
    757   }
    758 
    759   //
    760   // From now on, the segment is headless
    761   //
    762   NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD);
    763   Nbuf->Tcp = NULL;
    764 
    765   //
    766   // Process the segment in LISTEN state.
    767   //
    768   if (Tcb->State == TCP_LISTEN) {
    769     //
    770     // First step: Check RST
    771     //
    772     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
    773       DEBUG ((EFI_D_WARN, "TcpInput: discard a reset segment "
    774         "for TCB %p in listening\n", Tcb));
    775 
    776       goto DISCARD;
    777     }
    778 
    779     //
    780     // Second step: Check ACK.
    781     // Any ACK sent to TCP in LISTEN is reseted.
    782     //
    783     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
    784       DEBUG ((EFI_D_WARN, "TcpInput: send reset because of"
    785         " segment with ACK for TCB %p in listening\n", Tcb));
    786 
    787       goto SEND_RESET;
    788     }
    789 
    790     //
    791     // Third step: Check SYN
    792     //
    793     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
    794       //
    795       // create a child TCB to handle the data
    796       //
    797       Parent  = Tcb;
    798 
    799       Tcb     = TcpCloneTcb (Parent);
    800       if (Tcb == NULL) {
    801         DEBUG ((EFI_D_ERROR, "TcpInput: discard a segment because"
    802           " failed to clone a child for TCB %p\n", Tcb));
    803 
    804         goto DISCARD;
    805       }
    806 
    807       DEBUG ((EFI_D_INFO, "TcpInput: create a child for TCB %p"
    808         " in listening\n", Tcb));
    809 
    810       //
    811       // init the TCB structure
    812       //
    813       Tcb->LocalEnd.Ip    = Dst;
    814       Tcb->LocalEnd.Port  = Head->DstPort;
    815       Tcb->RemoteEnd.Ip   = Src;
    816       Tcb->RemoteEnd.Port = Head->SrcPort;
    817 
    818       TcpInitTcbLocal (Tcb);
    819       TcpInitTcbPeer (Tcb, Seg, &Option);
    820 
    821       TcpSetState (Tcb, TCP_SYN_RCVD);
    822       TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
    823       TcpTrimInWnd (Tcb, Nbuf);
    824 
    825       goto StepSix;
    826     }
    827 
    828     goto DISCARD;
    829 
    830   } else if (Tcb->State == TCP_SYN_SENT) {
    831     //
    832     // First step: Check ACK bit
    833     //
    834     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK) && (Seg->Ack != Tcb->Iss + 1)) {
    835 
    836       DEBUG ((EFI_D_WARN, "TcpInput: send reset because of "
    837         "wrong ACK received for TCB %p in SYN_SENT\n", Tcb));
    838 
    839       goto SEND_RESET;
    840     }
    841 
    842     //
    843     // Second step: Check RST bit
    844     //
    845     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
    846 
    847       if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
    848 
    849         DEBUG ((EFI_D_WARN, "TcpInput: connection reset by"
    850           " peer for TCB %p in SYN_SENT\n", Tcb));
    851 
    852         SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
    853         goto DROP_CONNECTION;
    854       } else {
    855 
    856         DEBUG ((EFI_D_WARN, "TcpInput: discard a reset segment "
    857           "because of no ACK for TCB %p in SYN_SENT\n", Tcb));
    858 
    859         goto DISCARD;
    860       }
    861     }
    862 
    863     //
    864     // Third step: Check security and precedence. Skipped
    865     //
    866 
    867     //
    868     // Fourth step: Check SYN. Pay attention to simultaneous open
    869     //
    870     if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
    871 
    872       TcpInitTcbPeer (Tcb, Seg, &Option);
    873 
    874       if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
    875 
    876         Tcb->SndUna = Seg->Ack;
    877       }
    878 
    879       TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
    880 
    881       if (TCP_SEQ_GT (Tcb->SndUna, Tcb->Iss)) {
    882 
    883         TcpSetState (Tcb, TCP_ESTABLISHED);
    884 
    885         TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
    886         TcpDeliverData (Tcb);
    887 
    888         if ((Tcb->CongestState == TCP_CONGEST_OPEN) &&
    889             TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
    890 
    891           TcpComputeRtt (Tcb, Tcb->RttMeasure);
    892           TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
    893         }
    894 
    895         TcpTrimInWnd (Tcb, Nbuf);
    896 
    897         TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
    898 
    899         DEBUG ((EFI_D_INFO, "TcpInput: connection established"
    900           " for TCB %p in SYN_SENT\n", Tcb));
    901 
    902         goto StepSix;
    903       } else {
    904         //
    905         // Received a SYN segment without ACK, simultaneous open.
    906         //
    907         TcpSetState (Tcb, TCP_SYN_RCVD);
    908 
    909         ASSERT (Tcb->SndNxt == Tcb->Iss + 1);
    910         TcpAdjustSndQue (Tcb, Tcb->SndNxt);
    911 
    912         TcpTrimInWnd (Tcb, Nbuf);
    913 
    914         DEBUG ((EFI_D_WARN, "TcpInput: simultaneous open "
    915           "for TCB %p in SYN_SENT\n", Tcb));
    916 
    917         goto StepSix;
    918       }
    919     }
    920 
    921     goto DISCARD;
    922   }
    923 
    924   //
    925   // Process segment in SYN_RCVD or TCP_CONNECTED states
    926   //
    927 
    928   //
    929   // Clear probe timer since the RecvWindow is opened.
    930   //
    931   if (Tcb->ProbeTimerOn && (Seg->Wnd != 0)) {
    932     TcpClearTimer (Tcb, TCP_TIMER_PROBE);
    933     Tcb->ProbeTimerOn = FALSE;
    934   }
    935 
    936   //
    937   // First step: Check whether SEG.SEQ is acceptable
    938   //
    939   if (TcpSeqAcceptable (Tcb, Seg) == 0) {
    940     DEBUG ((EFI_D_WARN, "TcpInput: sequence acceptance"
    941       " test failed for segment of TCB %p\n", Tcb));
    942 
    943     if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
    944       TcpSendAck (Tcb);
    945     }
    946 
    947     goto DISCARD;
    948   }
    949 
    950   if ((TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2)) &&
    951       (Tcb->RcvWl2 == Seg->End) &&
    952       !TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN | TCP_FLG_FIN)) {
    953 
    954     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
    955   }
    956 
    957   //
    958   // Second step: Check the RST
    959   //
    960   if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
    961 
    962     DEBUG ((EFI_D_WARN, "TcpInput: connection reset for TCB %p\n", Tcb));
    963 
    964     if (Tcb->State == TCP_SYN_RCVD) {
    965 
    966       SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED);
    967 
    968       //
    969       // This TCB comes from either a LISTEN TCB,
    970       // or active open TCB with simultanous open.
    971       // Do NOT signal user CONNECTION refused
    972       // if it comes from a LISTEN TCB.
    973       //
    974     } else if ((Tcb->State == TCP_ESTABLISHED) ||
    975                (Tcb->State == TCP_FIN_WAIT_1) ||
    976                (Tcb->State == TCP_FIN_WAIT_2) ||
    977                (Tcb->State == TCP_CLOSE_WAIT)) {
    978 
    979       SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
    980 
    981     } else {
    982 
    983     }
    984 
    985     goto DROP_CONNECTION;
    986   }
    987 
    988   //
    989   // Trim the data and flags.
    990   //
    991   TcpTrimInWnd (Tcb, Nbuf);
    992 
    993   //
    994   // Third step: Check security and precedence, Ignored
    995   //
    996 
    997   //
    998   // Fourth step: Check the SYN bit.
    999   //
   1000   if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
   1001 
   1002     DEBUG ((EFI_D_WARN, "TcpInput: connection reset "
   1003       "because received extra SYN for TCB %p\n", Tcb));
   1004 
   1005     SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
   1006     goto RESET_THEN_DROP;
   1007   }
   1008 
   1009   //
   1010   // Fifth step: Check the ACK
   1011   //
   1012   if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
   1013     DEBUG ((EFI_D_WARN, "TcpInput: segment discard because"
   1014       " of no ACK for connected TCB %p\n", Tcb));
   1015 
   1016     goto DISCARD;
   1017 
   1018   }
   1019 
   1020   if (Tcb->State == TCP_SYN_RCVD) {
   1021 
   1022     if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) &&
   1023         TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt)) {
   1024 
   1025       Tcb->SndWnd     = Seg->Wnd;
   1026       Tcb->SndWndMax  = MAX (Tcb->SndWnd, Tcb->SndWndMax);
   1027       Tcb->SndWl1     = Seg->Seq;
   1028       Tcb->SndWl2     = Seg->Ack;
   1029       TcpSetState (Tcb, TCP_ESTABLISHED);
   1030 
   1031       TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
   1032       TcpDeliverData (Tcb);
   1033 
   1034       DEBUG ((EFI_D_INFO, "TcpInput: connection established "
   1035         " for TCB %p in SYN_RCVD\n", Tcb));
   1036 
   1037       //
   1038       // Continue the process as ESTABLISHED state
   1039       //
   1040     } else {
   1041       DEBUG ((EFI_D_WARN, "TcpInput: send reset because of"
   1042         " wrong ACK for TCB %p in SYN_RCVD\n", Tcb));
   1043 
   1044       goto SEND_RESET;
   1045     }
   1046   }
   1047 
   1048   if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) {
   1049 
   1050     DEBUG ((EFI_D_WARN, "TcpInput: ignore the out-of-data"
   1051       " ACK for connected TCB %p\n", Tcb));
   1052 
   1053     goto StepSix;
   1054 
   1055   } else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) {
   1056 
   1057     DEBUG ((EFI_D_WARN, "TcpInput: discard segment for "
   1058       "future ACK for connected TCB %p\n", Tcb));
   1059 
   1060     TcpSendAck (Tcb);
   1061     goto DISCARD;
   1062   }
   1063 
   1064   //
   1065   // From now on: SND.UNA <= SEG.ACK <= SND.NXT.
   1066   //
   1067   if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) {
   1068     //
   1069     // update TsRecent as specified in page 16 RFC1323.
   1070     // RcvWl2 equals to the variable "LastAckSent"
   1071     // defined there.
   1072     //
   1073     if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) &&
   1074         TCP_SEQ_LT (Tcb->RcvWl2, Seg->End)) {
   1075 
   1076       Tcb->TsRecent     = Option.TSVal;
   1077       Tcb->TsRecentAge  = mTcpTick;
   1078     }
   1079 
   1080     TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr));
   1081 
   1082   } else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
   1083 
   1084     ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN);
   1085 
   1086     TcpComputeRtt (Tcb, Tcb->RttMeasure);
   1087     TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
   1088   }
   1089 
   1090   if (Seg->Ack == Tcb->SndNxt) {
   1091 
   1092     TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
   1093   } else {
   1094 
   1095     TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
   1096   }
   1097 
   1098   //
   1099   // Count duplicate acks.
   1100   //
   1101   if ((Seg->Ack == Tcb->SndUna) &&
   1102       (Tcb->SndUna != Tcb->SndNxt) &&
   1103       (Seg->Wnd == Tcb->SndWnd) &&
   1104       (0 == Len)) {
   1105 
   1106     Tcb->DupAck++;
   1107   } else {
   1108 
   1109     Tcb->DupAck = 0;
   1110   }
   1111 
   1112   //
   1113   // Congestion avoidance, fast recovery and fast retransmission.
   1114   //
   1115   if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) ||
   1116       (Tcb->CongestState == TCP_CONGEST_LOSS)) {
   1117 
   1118     if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
   1119 
   1120       if (Tcb->CWnd < Tcb->Ssthresh) {
   1121 
   1122         Tcb->CWnd += Tcb->SndMss;
   1123       } else {
   1124 
   1125         Tcb->CWnd += MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1);
   1126       }
   1127 
   1128       Tcb->CWnd = MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale);
   1129     }
   1130 
   1131     if (Tcb->CongestState == TCP_CONGEST_LOSS) {
   1132       TcpFastLossRecover (Tcb, Seg);
   1133     }
   1134   } else {
   1135 
   1136     TcpFastRecover (Tcb, Seg);
   1137   }
   1138 
   1139   if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
   1140 
   1141     TcpAdjustSndQue (Tcb, Seg->Ack);
   1142     Tcb->SndUna = Seg->Ack;
   1143 
   1144     if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&
   1145         TCP_SEQ_LT (Tcb->SndUp, Seg->Ack)) {
   1146 
   1147       TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
   1148     }
   1149   }
   1150 
   1151   //
   1152   // Update window info
   1153   //
   1154   if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) ||
   1155       ((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack))) {
   1156 
   1157     Right = Seg->Ack + Seg->Wnd;
   1158 
   1159     if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) {
   1160 
   1161       if ((Tcb->SndWl1 == Seg->Seq) &&
   1162           (Tcb->SndWl2 == Seg->Ack) &&
   1163           (Len == 0)) {
   1164 
   1165         goto NO_UPDATE;
   1166       }
   1167 
   1168       DEBUG ((EFI_D_WARN, "TcpInput: peer shrinks the"
   1169         " window for connected TCB %p\n", Tcb));
   1170 
   1171       if ((Tcb->CongestState == TCP_CONGEST_RECOVER) &&
   1172           (TCP_SEQ_LT (Right, Tcb->Recover))) {
   1173 
   1174         Tcb->Recover = Right;
   1175       }
   1176 
   1177       if ((Tcb->CongestState == TCP_CONGEST_LOSS) &&
   1178           (TCP_SEQ_LT (Right, Tcb->LossRecover))) {
   1179 
   1180         Tcb->LossRecover = Right;
   1181       }
   1182 
   1183       if (TCP_SEQ_LT (Right, Tcb->SndNxt)) {
   1184 
   1185         Tcb->SndNxt = Right;
   1186 
   1187         if (Right == Tcb->SndUna) {
   1188 
   1189           TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
   1190           TcpSetProbeTimer (Tcb);
   1191         }
   1192       }
   1193     }
   1194 
   1195     Tcb->SndWnd     = Seg->Wnd;
   1196     Tcb->SndWndMax  = MAX (Tcb->SndWnd, Tcb->SndWndMax);
   1197     Tcb->SndWl1     = Seg->Seq;
   1198     Tcb->SndWl2     = Seg->Ack;
   1199   }
   1200 
   1201 NO_UPDATE:
   1202 
   1203   if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) &&
   1204       (Tcb->SndUna == Tcb->SndNxt)) {
   1205 
   1206     DEBUG ((EFI_D_INFO, "TcpInput: local FIN is ACKed by"
   1207       " peer for connected TCB %p\n", Tcb));
   1208 
   1209     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED);
   1210   }
   1211 
   1212   //
   1213   // Transit the state if proper.
   1214   //
   1215   switch (Tcb->State) {
   1216   case TCP_FIN_WAIT_1:
   1217 
   1218     if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
   1219 
   1220       TcpSetState (Tcb, TCP_FIN_WAIT_2);
   1221 
   1222       TcpClearAllTimer (Tcb);
   1223       TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout);
   1224     }
   1225 
   1226   case TCP_FIN_WAIT_2:
   1227 
   1228     break;
   1229 
   1230   case TCP_CLOSE_WAIT:
   1231     break;
   1232 
   1233   case TCP_CLOSING:
   1234 
   1235     if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
   1236 
   1237       TcpSetState (Tcb, TCP_TIME_WAIT);
   1238 
   1239       TcpClearAllTimer (Tcb);
   1240 
   1241       if (Tcb->TimeWaitTimeout != 0) {
   1242 
   1243         TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
   1244       } else {
   1245 
   1246         DEBUG ((EFI_D_WARN, "Connection closed immediately "
   1247           "because app disables TIME_WAIT timer for %p\n", Tcb));
   1248 
   1249         TcpClose (Tcb);
   1250       }
   1251     }
   1252     break;
   1253 
   1254   case TCP_LAST_ACK:
   1255 
   1256     if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
   1257 
   1258       TcpSetState (Tcb, TCP_CLOSED);
   1259     }
   1260 
   1261     break;
   1262 
   1263   case TCP_TIME_WAIT:
   1264 
   1265     TcpSendAck (Tcb);
   1266 
   1267     if (Tcb->TimeWaitTimeout != 0) {
   1268 
   1269       TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
   1270     } else {
   1271 
   1272       DEBUG ((EFI_D_WARN, "Connection closed immediately "
   1273         "because app disables TIME_WAIT timer for %p\n", Tcb));
   1274 
   1275       TcpClose (Tcb);
   1276     }
   1277     break;
   1278 
   1279   default:
   1280     break;
   1281   }
   1282 
   1283   //
   1284   // Sixth step: Check the URG bit.update the Urg point
   1285   // if in TCP_CAN_RECV, otherwise, leave the RcvUp intact.
   1286   //
   1287 StepSix:
   1288 
   1289   Tcb->Idle = 0;
   1290   TcpSetKeepaliveTimer (Tcb);
   1291 
   1292   if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) &&
   1293       !TCP_FIN_RCVD (Tcb->State))
   1294   {
   1295 
   1296     DEBUG ((EFI_D_INFO, "TcpInput: received urgent data "
   1297       "from peer for connected TCB %p\n", Tcb));
   1298 
   1299     Urg = Seg->Seq + Seg->Urg;
   1300 
   1301     if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&
   1302         TCP_SEQ_GT (Urg, Tcb->RcvUp)) {
   1303 
   1304       Tcb->RcvUp = Urg;
   1305     } else {
   1306 
   1307       Tcb->RcvUp = Urg;
   1308       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG);
   1309     }
   1310   }
   1311 
   1312   //
   1313   // Seventh step: Process the segment data
   1314   //
   1315   if (Seg->End != Seg->Seq) {
   1316 
   1317     if (TCP_FIN_RCVD (Tcb->State)) {
   1318 
   1319       DEBUG ((EFI_D_WARN, "TcpInput: connection reset because"
   1320         " data is lost for connected TCB %p\n", Tcb));
   1321 
   1322       goto RESET_THEN_DROP;
   1323     }
   1324 
   1325     if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) {
   1326       DEBUG ((EFI_D_WARN, "TcpInput: connection reset because"
   1327         " data is lost for connected TCB %p\n", Tcb));
   1328 
   1329       goto RESET_THEN_DROP;
   1330     }
   1331 
   1332     TcpQueueData (Tcb, Nbuf);
   1333     if (TcpDeliverData (Tcb) == -1) {
   1334       goto RESET_THEN_DROP;
   1335     }
   1336 
   1337     if (!IsListEmpty (&Tcb->RcvQue)) {
   1338       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
   1339     }
   1340   }
   1341 
   1342   //
   1343   // Eighth step: check the FIN.
   1344   // This step is moved to TcpDeliverData. FIN will be
   1345   // processed in sequence there. Check the comments in
   1346   // the beginning of the file header for information.
   1347   //
   1348 
   1349   //
   1350   // Tcb is a new child of the listening Parent,
   1351   // commit it.
   1352   //
   1353   if (Parent != NULL) {
   1354     Tcb->Parent = Parent;
   1355     TcpInsertTcb (Tcb);
   1356   }
   1357 
   1358   if ((Tcb->State != TCP_CLOSED) &&
   1359       (TcpToSendData (Tcb, 0) == 0) &&
   1360       (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Nbuf->TotalSize != 0))) {
   1361 
   1362     TcpToSendAck (Tcb);
   1363   }
   1364 
   1365   NetbufFree (Nbuf);
   1366   return 0;
   1367 
   1368 RESET_THEN_DROP:
   1369   TcpSendReset (Tcb, Head, Len, Dst, Src);
   1370 
   1371 DROP_CONNECTION:
   1372   ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
   1373 
   1374   NetbufFree (Nbuf);
   1375   TcpClose (Tcb);
   1376 
   1377   return -1;
   1378 
   1379 SEND_RESET:
   1380 
   1381   TcpSendReset (Tcb, Head, Len, Dst, Src);
   1382 
   1383 DISCARD:
   1384 
   1385   //
   1386   // Tcb is a child of Parent, and it doesn't survive
   1387   //
   1388   DEBUG ((EFI_D_WARN, "Tcp4Input: Discard a packet\n"));
   1389   NetbufFree (Nbuf);
   1390 
   1391   if ((Parent != NULL) && (Tcb != NULL)) {
   1392 
   1393     ASSERT (Tcb->Sk != NULL);
   1394     TcpClose (Tcb);
   1395   }
   1396 
   1397   return 0;
   1398 }
   1399 
   1400 
   1401 /**
   1402   Process the received ICMP error messages for TCP.
   1403 
   1404   @param  Nbuf     Buffer that contains part of the TCP segment without IP header
   1405                    truncated from the ICMP error packet.
   1406   @param  IcmpErr  The ICMP error code interpreted from ICMP error packet.
   1407   @param  Src      Source address of the ICMP error message.
   1408   @param  Dst      Destination address of the ICMP error message.
   1409 
   1410 **/
   1411 VOID
   1412 TcpIcmpInput (
   1413   IN NET_BUF     *Nbuf,
   1414   IN UINT8       IcmpErr,
   1415   IN UINT32      Src,
   1416   IN UINT32      Dst
   1417   )
   1418 {
   1419   TCP_HEAD         *Head;
   1420   TCP_CB           *Tcb;
   1421   TCP_SEQNO        Seq;
   1422   EFI_STATUS       IcmpErrStatus;
   1423   BOOLEAN          IcmpErrIsHard;
   1424   BOOLEAN          IcmpErrNotify;
   1425 
   1426   Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
   1427   ASSERT (Head != NULL);
   1428   Tcb = TcpLocateTcb (
   1429           Head->DstPort,
   1430           Dst,
   1431           Head->SrcPort,
   1432           Src,
   1433           FALSE
   1434           );
   1435   if (Tcb == NULL || Tcb->State == TCP_CLOSED) {
   1436 
   1437     goto CLEAN_EXIT;
   1438   }
   1439 
   1440   //
   1441   // Validate the sequence number.
   1442   //
   1443   Seq = NTOHL (Head->Seq);
   1444   if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) {
   1445 
   1446     goto CLEAN_EXIT;
   1447   }
   1448 
   1449   IcmpErrStatus = IpIoGetIcmpErrStatus (
   1450                     IcmpErr,
   1451                     IP_VERSION_4,
   1452                     &IcmpErrIsHard,
   1453                     &IcmpErrNotify
   1454                     );
   1455 
   1456   if (IcmpErrNotify) {
   1457 
   1458     SOCK_ERROR (Tcb->Sk, IcmpErrStatus);
   1459   }
   1460 
   1461   if (IcmpErrIsHard) {
   1462 
   1463     TcpClose (Tcb);
   1464   }
   1465 
   1466 CLEAN_EXIT:
   1467   NetbufFree (Nbuf);
   1468 }
   1469