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