Home | History | Annotate | Download | only in Tcp4Dxe
      1 /** @file
      2   Tcp request dispatcher implementation.
      3 
      4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
      5 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php<BR>
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Tcp4Main.h"
     17 
     18 #define TCP_COMP_VAL(Min, Max, Default, Val) \
     19   ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
     20 
     21 /**
     22   Add or remove a route entry in the IP route table associated with this TCP instance.
     23 
     24   @param  Tcb                   Pointer to the TCP_CB of this TCP instance.
     25   @param  RouteInfo             Pointer to the route info to be processed.
     26 
     27   @retval EFI_SUCCESS           The operation completed successfully.
     28   @retval EFI_NOT_STARTED       The driver instance has not been started.
     29   @retval EFI_NO_MAPPING        When using the default address, configuration(DHCP,
     30                                 BOOTP, RARP, etc.) is not finished yet.
     31   @retval EFI_OUT_OF_RESOURCES  Could not add the entry to the routing table.
     32   @retval EFI_NOT_FOUND         This route is not in the routing table
     33                                 (when RouteInfo->DeleteRoute is TRUE).
     34   @retval EFI_ACCESS_DENIED     The route is already defined in the routing table
     35                                 (when RouteInfo->DeleteRoute is FALSE).
     36 **/
     37 EFI_STATUS
     38 Tcp4Route (
     39   IN TCP_CB           *Tcb,
     40   IN TCP4_ROUTE_INFO  *RouteInfo
     41   )
     42 {
     43   EFI_IP4_PROTOCOL  *Ip4;
     44 
     45   Ip4 = Tcb->IpInfo->Ip.Ip4;
     46 
     47   ASSERT (Ip4 != NULL);
     48 
     49   return Ip4->Routes (
     50               Ip4,
     51               RouteInfo->DeleteRoute,
     52               RouteInfo->SubnetAddress,
     53               RouteInfo->SubnetMask,
     54               RouteInfo->GatewayAddress
     55               );
     56 
     57 }
     58 
     59 
     60 /**
     61   Get the operational settings of this TCP instance.
     62 
     63   @param  Tcb                    Pointer to the TCP_CB of this TCP instance.
     64   @param  Mode                   Pointer to the buffer to store the operational
     65                                  settings.
     66 
     67   @retval EFI_SUCCESS            The mode data is read.
     68   @retval EFI_NOT_STARTED        No configuration data is available because this
     69                                  instance hasn't been started.
     70 
     71 **/
     72 EFI_STATUS
     73 Tcp4GetMode (
     74   IN     TCP_CB         *Tcb,
     75   IN OUT TCP4_MODE_DATA *Mode
     76   )
     77 {
     78   SOCKET                *Sock;
     79   EFI_TCP4_CONFIG_DATA  *ConfigData;
     80   EFI_TCP4_ACCESS_POINT *AccessPoint;
     81   EFI_TCP4_OPTION       *Option;
     82   EFI_IP4_PROTOCOL      *Ip;
     83 
     84   Sock = Tcb->Sk;
     85 
     86   if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
     87     return EFI_NOT_STARTED;
     88   }
     89 
     90   if (Mode->Tcp4State != NULL) {
     91     *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;
     92   }
     93 
     94   if (Mode->Tcp4ConfigData != NULL) {
     95 
     96     ConfigData                      = Mode->Tcp4ConfigData;
     97     AccessPoint                     = &(ConfigData->AccessPoint);
     98     Option                          = ConfigData->ControlOption;
     99 
    100     ConfigData->TypeOfService       = Tcb->Tos;
    101     ConfigData->TimeToLive          = Tcb->Ttl;
    102 
    103     AccessPoint->UseDefaultAddress  = Tcb->UseDefaultAddr;
    104 
    105     IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
    106     IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask);
    107     AccessPoint->StationPort        = NTOHS (Tcb->LocalEnd.Port);
    108 
    109     IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
    110     AccessPoint->RemotePort         = NTOHS (Tcb->RemoteEnd.Port);
    111     AccessPoint->ActiveFlag         = (BOOLEAN) (Tcb->State != TCP_LISTEN);
    112 
    113     if (Option != NULL) {
    114       Option->ReceiveBufferSize       = GET_RCV_BUFFSIZE (Tcb->Sk);
    115       Option->SendBufferSize          = GET_SND_BUFFSIZE (Tcb->Sk);
    116       Option->MaxSynBackLog           = GET_BACKLOG (Tcb->Sk);
    117 
    118       Option->ConnectionTimeout       = Tcb->ConnectTimeout / TCP_TICK_HZ;
    119       Option->DataRetries             = Tcb->MaxRexmit;
    120       Option->FinTimeout              = Tcb->FinWait2Timeout / TCP_TICK_HZ;
    121       Option->TimeWaitTimeout         = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
    122       Option->KeepAliveProbes         = Tcb->MaxKeepAlive;
    123       Option->KeepAliveTime           = Tcb->KeepAliveIdle / TCP_TICK_HZ;
    124       Option->KeepAliveInterval       = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
    125 
    126       Option->EnableNagle         = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
    127       Option->EnableTimeStamp     = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
    128       Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
    129 
    130       Option->EnableSelectiveAck      = FALSE;
    131       Option->EnablePathMtuDiscovery  = FALSE;
    132     }
    133   }
    134 
    135   Ip = Tcb->IpInfo->Ip.Ip4;
    136   ASSERT (Ip != NULL);
    137 
    138   return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
    139 }
    140 
    141 
    142 /**
    143   If AP->StationPort isn't zero, check whether the access point
    144   is registered, else generate a random station port for this
    145   access point.
    146 
    147   @param  AP                     Pointer to the access point.
    148 
    149   @retval EFI_SUCCESS            The check is passed or the port is assigned.
    150   @retval EFI_INVALID_PARAMETER  The non-zero station port is already used.
    151   @retval EFI_OUT_OF_RESOURCES   No port can be allocated.
    152 
    153 **/
    154 EFI_STATUS
    155 Tcp4Bind (
    156   IN EFI_TCP4_ACCESS_POINT *AP
    157   )
    158 {
    159   BOOLEAN Cycle;
    160 
    161   if (0 != AP->StationPort) {
    162     //
    163     // check if a same endpoint is bound
    164     //
    165     if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
    166 
    167       return EFI_INVALID_PARAMETER;
    168     }
    169   } else {
    170     //
    171     // generate a random port
    172     //
    173     Cycle = FALSE;
    174 
    175     if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
    176       mTcp4RandomPort = TCP4_PORT_KNOWN;
    177     }
    178 
    179     mTcp4RandomPort++;
    180 
    181     while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
    182 
    183       mTcp4RandomPort++;
    184 
    185       if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
    186 
    187         if (Cycle) {
    188           DEBUG ((EFI_D_ERROR, "Tcp4Bind: no port can be allocated "
    189             "for this pcb\n"));
    190 
    191           return EFI_OUT_OF_RESOURCES;
    192         }
    193 
    194         mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
    195 
    196         Cycle = TRUE;
    197       }
    198 
    199     }
    200 
    201     AP->StationPort = mTcp4RandomPort;
    202   }
    203 
    204   return EFI_SUCCESS;
    205 }
    206 
    207 
    208 /**
    209   Flush the Tcb add its associated protocols.
    210 
    211   @param  Tcb                    Pointer to the TCP_CB to be flushed.
    212 
    213 **/
    214 VOID
    215 Tcp4FlushPcb (
    216   IN TCP_CB *Tcb
    217   )
    218 {
    219   SOCKET           *Sock;
    220 
    221   IpIoConfigIp (Tcb->IpInfo, NULL);
    222 
    223   Sock     = Tcb->Sk;
    224 
    225   if (SOCK_IS_CONFIGURED (Sock)) {
    226     RemoveEntryList (&Tcb->List);
    227 
    228     //
    229     // Uninstall the device path protocol.
    230     //
    231     if (Sock->DevicePath != NULL) {
    232       gBS->UninstallProtocolInterface (
    233              Sock->SockHandle,
    234              &gEfiDevicePathProtocolGuid,
    235              Sock->DevicePath
    236              );
    237       FreePool (Sock->DevicePath);
    238     }
    239   }
    240 
    241   NetbufFreeList (&Tcb->SndQue);
    242   NetbufFreeList (&Tcb->RcvQue);
    243   Tcb->State = TCP_CLOSED;
    244 }
    245 
    246 /**
    247   Attach a Pcb to the socket.
    248 
    249   @param  Sk                     Pointer to the socket of this TCP instance.
    250 
    251   @retval EFI_SUCCESS            The operation is completed successfully.
    252   @retval EFI_OUT_OF_RESOURCES   Failed due to resource limit.
    253 
    254 **/
    255 EFI_STATUS
    256 Tcp4AttachPcb (
    257   IN SOCKET  *Sk
    258   )
    259 {
    260   TCP_CB            *Tcb;
    261   TCP4_PROTO_DATA   *ProtoData;
    262   IP_IO             *IpIo;
    263   EFI_STATUS        Status;
    264   VOID              *Ip;
    265 
    266   Tcb = AllocateZeroPool (sizeof (TCP_CB));
    267 
    268   if (Tcb == NULL) {
    269 
    270     DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
    271 
    272     return EFI_OUT_OF_RESOURCES;
    273   }
    274 
    275   ProtoData  = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
    276   IpIo       = ProtoData->TcpService->IpIo;
    277 
    278   //
    279   // Create an IpInfo for this Tcb.
    280   //
    281   Tcb->IpInfo = IpIoAddIp (IpIo);
    282   if (Tcb->IpInfo == NULL) {
    283 
    284     FreePool (Tcb);
    285     return EFI_OUT_OF_RESOURCES;
    286   }
    287 
    288   //
    289   // Open the new created IP instance BY_CHILD.
    290   //
    291   Status = gBS->OpenProtocol (
    292                   Tcb->IpInfo->ChildHandle,
    293                   &gEfiIp4ProtocolGuid,
    294                   &Ip,
    295                   IpIo->Image,
    296                   Sk->SockHandle,
    297                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    298                   );
    299   if (EFI_ERROR (Status)) {
    300     IpIoRemoveIp (IpIo, Tcb->IpInfo);
    301     return Status;
    302   }
    303 
    304   InitializeListHead (&Tcb->List);
    305   InitializeListHead (&Tcb->SndQue);
    306   InitializeListHead (&Tcb->RcvQue);
    307 
    308   Tcb->State        = TCP_CLOSED;
    309   Tcb->Sk           = Sk;
    310   ProtoData->TcpPcb = Tcb;
    311 
    312   return EFI_SUCCESS;
    313 }
    314 
    315 /**
    316   Detach the Pcb of the socket.
    317 
    318   @param  Sk                     Pointer to the socket of this TCP instance.
    319 
    320 **/
    321 VOID
    322 Tcp4DetachPcb (
    323   IN SOCKET  *Sk
    324   )
    325 {
    326   TCP4_PROTO_DATA  *ProtoData;
    327   TCP_CB           *Tcb;
    328 
    329   ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
    330   Tcb       = ProtoData->TcpPcb;
    331 
    332   ASSERT (Tcb != NULL);
    333 
    334   Tcp4FlushPcb (Tcb);
    335 
    336   //
    337   // Close the IP protocol.
    338   //
    339   gBS->CloseProtocol (
    340          Tcb->IpInfo->ChildHandle,
    341          &gEfiIp4ProtocolGuid,
    342          ProtoData->TcpService->IpIo->Image,
    343          Sk->SockHandle
    344          );
    345 
    346   IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
    347 
    348   FreePool (Tcb);
    349 
    350   ProtoData->TcpPcb = NULL;
    351 }
    352 
    353 
    354 /**
    355   Configure the Pcb using CfgData.
    356 
    357   @param  Sk                     Pointer to the socket of this TCP instance.
    358   @param  CfgData                Pointer to the TCP configuration data.
    359 
    360   @retval EFI_SUCCESS            The operation is completed successfully.
    361   @retval EFI_INVALID_PARAMETER  A same access point has been configured in
    362                                  another TCP instance.
    363   @retval EFI_OUT_OF_RESOURCES   Failed due to resource limit.
    364 
    365 **/
    366 EFI_STATUS
    367 Tcp4ConfigurePcb (
    368   IN SOCKET               *Sk,
    369   IN EFI_TCP4_CONFIG_DATA *CfgData
    370   )
    371 {
    372   EFI_IP4_CONFIG_DATA IpCfgData;
    373   EFI_STATUS          Status;
    374   EFI_TCP4_OPTION     *Option;
    375   TCP4_PROTO_DATA     *TcpProto;
    376   TCP_CB              *Tcb;
    377 
    378   ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
    379 
    380   TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
    381   Tcb      = TcpProto->TcpPcb;
    382 
    383   ASSERT (Tcb != NULL);
    384 
    385   //
    386   // Add Ip for send pkt to the peer
    387   //
    388   CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData));
    389   IpCfgData.DefaultProtocol   = EFI_IP_PROTO_TCP;
    390   IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
    391   IpCfgData.StationAddress    = CfgData->AccessPoint.StationAddress;
    392   IpCfgData.SubnetMask        = CfgData->AccessPoint.SubnetMask;
    393   IpCfgData.ReceiveTimeout    = (UINT32) (-1);
    394 
    395   //
    396   // Configure the IP instance this Tcb consumes.
    397   //
    398   Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
    399   if (EFI_ERROR (Status)) {
    400     goto OnExit;
    401   }
    402 
    403   //
    404   // Get the default address info if the instance is configured to use default address.
    405   //
    406   if (CfgData->AccessPoint.UseDefaultAddress) {
    407     CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
    408     CfgData->AccessPoint.SubnetMask     = IpCfgData.SubnetMask;
    409   }
    410 
    411   //
    412   // check if we can bind this endpoint in CfgData
    413   //
    414   Status = Tcp4Bind (&(CfgData->AccessPoint));
    415 
    416   if (EFI_ERROR (Status)) {
    417     DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed "
    418       "with %r\n", Status));
    419 
    420     goto OnExit;
    421   }
    422 
    423   //
    424   // Initalize the operating information in this Tcb
    425   //
    426   ASSERT (Tcb->State == TCP_CLOSED &&
    427     IsListEmpty (&Tcb->SndQue) &&
    428     IsListEmpty (&Tcb->RcvQue));
    429 
    430   TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
    431   Tcb->State            = TCP_CLOSED;
    432 
    433   Tcb->SndMss           = 536;
    434   Tcb->RcvMss           = TcpGetRcvMss (Sk);
    435 
    436   Tcb->SRtt             = 0;
    437   Tcb->Rto              = 3 * TCP_TICK_HZ;
    438 
    439   Tcb->CWnd             = Tcb->SndMss;
    440   Tcb->Ssthresh         = 0xffffffff;
    441 
    442   Tcb->CongestState     = TCP_CONGEST_OPEN;
    443 
    444   Tcb->KeepAliveIdle    = TCP_KEEPALIVE_IDLE_MIN;
    445   Tcb->KeepAlivePeriod  = TCP_KEEPALIVE_PERIOD;
    446   Tcb->MaxKeepAlive     = TCP_MAX_KEEPALIVE;
    447   Tcb->MaxRexmit        = TCP_MAX_LOSS;
    448   Tcb->FinWait2Timeout  = TCP_FIN_WAIT2_TIME;
    449   Tcb->TimeWaitTimeout  = TCP_TIME_WAIT_TIME;
    450   Tcb->ConnectTimeout   = TCP_CONNECT_TIME;
    451 
    452   //
    453   // initialize Tcb in the light of CfgData
    454   //
    455   Tcb->Ttl            = CfgData->TimeToLive;
    456   Tcb->Tos            = CfgData->TypeOfService;
    457 
    458   Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;
    459 
    460   CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
    461   Tcb->LocalEnd.Port  = HTONS (CfgData->AccessPoint.StationPort);
    462   IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->AccessPoint.SubnetMask);
    463 
    464   if (CfgData->AccessPoint.ActiveFlag) {
    465     CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
    466     Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
    467   } else {
    468     Tcb->RemoteEnd.Ip   = 0;
    469     Tcb->RemoteEnd.Port = 0;
    470   }
    471 
    472   Option              = CfgData->ControlOption;
    473 
    474   if (Option != NULL) {
    475     SET_RCV_BUFFSIZE (
    476       Sk,
    477       (UINT32) (TCP_COMP_VAL (
    478                   TCP_RCV_BUF_SIZE_MIN,
    479                   TCP_RCV_BUF_SIZE,
    480                   TCP_RCV_BUF_SIZE,
    481                   Option->ReceiveBufferSize
    482                   )
    483                )
    484       );
    485     SET_SND_BUFFSIZE (
    486       Sk,
    487       (UINT32) (TCP_COMP_VAL (
    488                   TCP_SND_BUF_SIZE_MIN,
    489                   TCP_SND_BUF_SIZE,
    490                   TCP_SND_BUF_SIZE,
    491                   Option->SendBufferSize
    492                   )
    493                )
    494       );
    495 
    496     SET_BACKLOG (
    497       Sk,
    498       (UINT32) (TCP_COMP_VAL (
    499                   TCP_BACKLOG_MIN,
    500                   TCP_BACKLOG,
    501                   TCP_BACKLOG,
    502                   Option->MaxSynBackLog
    503                   )
    504                )
    505       );
    506 
    507     Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
    508                                 TCP_MAX_LOSS_MIN,
    509                                 TCP_MAX_LOSS,
    510                                 TCP_MAX_LOSS,
    511                                 Option->DataRetries
    512                                 );
    513     Tcb->FinWait2Timeout = TCP_COMP_VAL (
    514                               TCP_FIN_WAIT2_TIME,
    515                               TCP_FIN_WAIT2_TIME_MAX,
    516                               TCP_FIN_WAIT2_TIME,
    517                               (UINT32) (Option->FinTimeout * TCP_TICK_HZ)
    518                               );
    519 
    520     if (Option->TimeWaitTimeout != 0) {
    521       Tcb->TimeWaitTimeout = TCP_COMP_VAL (
    522                                TCP_TIME_WAIT_TIME,
    523                                TCP_TIME_WAIT_TIME_MAX,
    524                                TCP_TIME_WAIT_TIME,
    525                                (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)
    526                                );
    527     } else {
    528       Tcb->TimeWaitTimeout = 0;
    529     }
    530 
    531     if (Option->KeepAliveProbes != 0) {
    532       TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
    533 
    534       Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
    535                                     TCP_MAX_KEEPALIVE_MIN,
    536                                     TCP_MAX_KEEPALIVE,
    537                                     TCP_MAX_KEEPALIVE,
    538                                     Option->KeepAliveProbes
    539                                     );
    540       Tcb->KeepAliveIdle = TCP_COMP_VAL (
    541                              TCP_KEEPALIVE_IDLE_MIN,
    542                              TCP_KEEPALIVE_IDLE_MAX,
    543                              TCP_KEEPALIVE_IDLE_MIN,
    544                              (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
    545                              );
    546       Tcb->KeepAlivePeriod = TCP_COMP_VAL (
    547                                TCP_KEEPALIVE_PERIOD_MIN,
    548                                TCP_KEEPALIVE_PERIOD,
    549                                TCP_KEEPALIVE_PERIOD,
    550                                (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
    551                                );
    552     }
    553 
    554     Tcb->ConnectTimeout = TCP_COMP_VAL (
    555                             TCP_CONNECT_TIME_MIN,
    556                             TCP_CONNECT_TIME,
    557                             TCP_CONNECT_TIME,
    558                             (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
    559                             );
    560 
    561     if (!Option->EnableNagle) {
    562       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
    563     }
    564 
    565     if (!Option->EnableTimeStamp) {
    566       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
    567     }
    568 
    569     if (!Option->EnableWindowScaling) {
    570       TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
    571     }
    572   }
    573 
    574   //
    575   // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
    576   // determined, construct the IP device path and install it.
    577   //
    578   Status = TcpInstallDevicePath (Sk);
    579   if (EFI_ERROR (Status)) {
    580     goto OnExit;
    581   }
    582 
    583   //
    584   // update state of Tcb and socket
    585   //
    586   if (!CfgData->AccessPoint.ActiveFlag) {
    587 
    588     TcpSetState (Tcb, TCP_LISTEN);
    589     SockSetState (Sk, SO_LISTENING);
    590 
    591     Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
    592   } else {
    593 
    594     Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
    595   }
    596 
    597   TcpInsertTcb (Tcb);
    598 
    599 OnExit:
    600 
    601   return Status;
    602 }
    603 
    604 
    605 /**
    606   The procotol handler provided to the socket layer, used to
    607   dispatch the socket level requests by calling the corresponding
    608   TCP layer functions.
    609 
    610   @param  Sock                   Pointer to the socket of this TCP instance.
    611   @param  Request                The code of this operation request.
    612   @param  Data                   Pointer to the operation specific data passed in
    613                                  together with the operation request.
    614 
    615   @retval EFI_SUCCESS            The socket request is completed successfully.
    616   @retval other                  The error status returned by the corresponding TCP
    617                                  layer function.
    618 
    619 **/
    620 EFI_STATUS
    621 Tcp4Dispatcher (
    622   IN SOCKET                  *Sock,
    623   IN UINT8                   Request,
    624   IN VOID                    *Data    OPTIONAL
    625   )
    626 {
    627   TCP_CB            *Tcb;
    628   TCP4_PROTO_DATA   *ProtoData;
    629   EFI_IP4_PROTOCOL  *Ip;
    630 
    631   ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
    632   Tcb       = ProtoData->TcpPcb;
    633 
    634   switch (Request) {
    635   case SOCK_POLL:
    636     Ip = ProtoData->TcpService->IpIo->Ip.Ip4;
    637     Ip->Poll (Ip);
    638     break;
    639 
    640   case SOCK_CONSUMED:
    641     //
    642     // After user received data from socket buffer, socket will
    643     // notify TCP using this message to give it a chance to send out
    644     // window update information
    645     //
    646     ASSERT (Tcb != NULL);
    647     TcpOnAppConsume (Tcb);
    648     break;
    649 
    650   case SOCK_SND:
    651 
    652     ASSERT (Tcb != NULL);
    653     TcpOnAppSend (Tcb);
    654     break;
    655 
    656   case SOCK_CLOSE:
    657 
    658     TcpOnAppClose (Tcb);
    659 
    660     break;
    661 
    662   case SOCK_ABORT:
    663 
    664     TcpOnAppAbort (Tcb);
    665 
    666     break;
    667 
    668   case SOCK_SNDPUSH:
    669     Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
    670     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
    671 
    672     break;
    673 
    674   case SOCK_SNDURG:
    675     Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
    676     TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
    677 
    678     break;
    679 
    680   case SOCK_CONNECT:
    681 
    682     TcpOnAppConnect (Tcb);
    683 
    684     break;
    685 
    686   case SOCK_ATTACH:
    687 
    688     return Tcp4AttachPcb (Sock);
    689 
    690   case SOCK_FLUSH:
    691 
    692     Tcp4FlushPcb (Tcb);
    693 
    694     break;
    695 
    696   case SOCK_DETACH:
    697 
    698     Tcp4DetachPcb (Sock);
    699 
    700     break;
    701 
    702   case SOCK_CONFIGURE:
    703 
    704     return Tcp4ConfigurePcb (
    705             Sock,
    706             (EFI_TCP4_CONFIG_DATA *) Data
    707             );
    708 
    709   case SOCK_MODE:
    710 
    711     ASSERT ((Data != NULL) && (Tcb != NULL));
    712 
    713     return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
    714 
    715   case SOCK_ROUTE:
    716 
    717     ASSERT ((Data != NULL) && (Tcb != NULL));
    718 
    719     return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
    720 
    721   default:
    722     return EFI_UNSUPPORTED;
    723   }
    724 
    725   return EFI_SUCCESS;
    726 
    727 }
    728