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