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