]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/TcpDispatcher.c
NetworkPkg: Convert non DOS format files to DOS format
[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
d551cc64 4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
a3bcde70
HT
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
a3bcde70
HT
307\r
308 IpIoConfigIp (Tcb->IpInfo, NULL);\r
309\r
310 Sock = Tcb->Sk;\r
a3bcde70
HT
311\r
312 if (SOCK_IS_CONFIGURED (Sock)) {\r
313 RemoveEntryList (&Tcb->List);\r
314\r
315 if (Sock->DevicePath != NULL) {\r
316 //\r
317 // Uninstall the device path protocl.\r
318 //\r
319 gBS->UninstallProtocolInterface (\r
320 Sock->SockHandle,\r
321 &gEfiDevicePathProtocolGuid,\r
322 Sock->DevicePath\r
323 );\r
324\r
325 FreePool (Sock->DevicePath);\r
326 Sock->DevicePath = NULL;\r
327 }\r
a3bcde70
HT
328 }\r
329\r
330 NetbufFreeList (&Tcb->SndQue);\r
331 NetbufFreeList (&Tcb->RcvQue);\r
332 Tcb->State = TCP_CLOSED;\r
9119637c 333 Tcb->RemoteIpZero = FALSE;\r
a3bcde70
HT
334}\r
335\r
336/**\r
337 Attach a Pcb to the socket.\r
338\r
339 @param[in] Sk Pointer to the socket of this TCP instance.\r
340\r
341 @retval EFI_SUCCESS The operation completed successfully.\r
342 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.\r
343\r
344**/\r
345EFI_STATUS\r
346TcpAttachPcb (\r
347 IN SOCKET *Sk\r
348 )\r
349{\r
350 TCP_CB *Tcb;\r
351 TCP_PROTO_DATA *ProtoData;\r
352 IP_IO *IpIo;\r
216f7970 353 EFI_STATUS Status;\r
354 VOID *Ip;\r
355 EFI_GUID *IpProtocolGuid;\r
a3bcde70 356\r
216f7970 357 if (Sk->IpVersion == IP_VERSION_4) {\r
358 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
359 } else {\r
360 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
361 }\r
362 \r
a3bcde70
HT
363 Tcb = AllocateZeroPool (sizeof (TCP_CB));\r
364\r
365 if (Tcb == NULL) {\r
366\r
367 DEBUG ((EFI_D_ERROR, "TcpConfigurePcb: failed to allocate a TCB\n"));\r
368\r
369 return EFI_OUT_OF_RESOURCES;\r
370 }\r
371\r
372 ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved;\r
373 IpIo = ProtoData->TcpService->IpIo;\r
374\r
375 //\r
376 // Create an IpInfo for this Tcb.\r
377 //\r
378 Tcb->IpInfo = IpIoAddIp (IpIo);\r
379 if (Tcb->IpInfo == NULL) {\r
380\r
381 FreePool (Tcb);\r
382 return EFI_OUT_OF_RESOURCES;\r
383 }\r
384\r
216f7970 385 //\r
386 // Open the new created IP instance BY_CHILD.\r
387 //\r
388 Status = gBS->OpenProtocol (\r
389 Tcb->IpInfo->ChildHandle,\r
390 IpProtocolGuid,\r
391 &Ip,\r
392 IpIo->Image,\r
393 Sk->SockHandle,\r
394 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
395 );\r
396 if (EFI_ERROR (Status)) {\r
397 IpIoRemoveIp (IpIo, Tcb->IpInfo);\r
398 return Status;\r
399 }\r
400 \r
a3bcde70
HT
401 InitializeListHead (&Tcb->List);\r
402 InitializeListHead (&Tcb->SndQue);\r
403 InitializeListHead (&Tcb->RcvQue);\r
404\r
405 Tcb->State = TCP_CLOSED;\r
406 Tcb->Sk = Sk;\r
407 ProtoData->TcpPcb = Tcb;\r
408\r
409 return EFI_SUCCESS;\r
410}\r
411\r
412/**\r
413 Detach the Pcb of the socket.\r
414\r
415 @param[in, out] Sk Pointer to the socket of this TCP instance.\r
416\r
417**/\r
418VOID\r
419TcpDetachPcb (\r
420 IN OUT SOCKET *Sk\r
421 )\r
422{\r
423 TCP_PROTO_DATA *ProtoData;\r
424 TCP_CB *Tcb;\r
216f7970 425 EFI_GUID *IpProtocolGuid;\r
a3bcde70 426\r
216f7970 427 if (Sk->IpVersion == IP_VERSION_4) {\r
428 IpProtocolGuid = &gEfiIp4ProtocolGuid;\r
429 } else {\r
430 IpProtocolGuid = &gEfiIp6ProtocolGuid;\r
431 }\r
432 \r
a3bcde70
HT
433 ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved;\r
434 Tcb = ProtoData->TcpPcb;\r
435\r
436 ASSERT (Tcb != NULL);\r
437\r
438 TcpFlushPcb (Tcb);\r
439\r
216f7970 440 //\r
441 // Close the IP protocol.\r
442 //\r
443 gBS->CloseProtocol (\r
444 Tcb->IpInfo->ChildHandle,\r
445 IpProtocolGuid,\r
446 ProtoData->TcpService->IpIo->Image,\r
447 Sk->SockHandle\r
448 );\r
449 \r
a3bcde70
HT
450 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);\r
451\r
452 FreePool (Tcb);\r
453\r
454 ProtoData->TcpPcb = NULL;\r
455}\r
456\r
457/**\r
458 Configure the Pcb using CfgData.\r
459\r
460 @param[in] Sk Pointer to the socket of this TCP instance.\r
461 @param[in] CfgData Pointer to the TCP configuration data.\r
462\r
463 @retval EFI_SUCCESS The operation completed successfully.\r
464 @retval EFI_INVALID_PARAMETER A same access point has been configured in\r
465 another TCP instance.\r
466 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.\r
467\r
468**/\r
469EFI_STATUS\r
470TcpConfigurePcb (\r
471 IN SOCKET *Sk,\r
472 IN TCP_CONFIG_DATA *CfgData\r
473 )\r
474{\r
475 IP_IO_IP_CONFIG_DATA IpCfgData;\r
476 EFI_STATUS Status;\r
477 EFI_TCP4_OPTION *Option;\r
478 TCP_PROTO_DATA *TcpProto;\r
479 TCP_CB *Tcb;\r
480 TCP_ACCESS_POINT *TcpAp;\r
481\r
482 ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));\r
483\r
484 TcpProto = (TCP_PROTO_DATA *) Sk->ProtoReserved;\r
485 Tcb = TcpProto->TcpPcb;\r
486\r
487 ASSERT (Tcb != NULL);\r
488\r
489 if (Sk->IpVersion == IP_VERSION_4) {\r
490 //\r
491 // Add Ip for send pkt to the peer\r
492 //\r
493 CopyMem (&IpCfgData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));\r
494 IpCfgData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
495 IpCfgData.Ip4CfgData.TypeOfService = CfgData->Tcp4CfgData.TypeOfService;\r
496 IpCfgData.Ip4CfgData.TimeToLive = CfgData->Tcp4CfgData.TimeToLive;\r
497 IpCfgData.Ip4CfgData.UseDefaultAddress = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;\r
498 IpCfgData.Ip4CfgData.SubnetMask = CfgData->Tcp4CfgData.AccessPoint.SubnetMask;\r
499 IpCfgData.Ip4CfgData.ReceiveTimeout = (UINT32) (-1);\r
500 CopyMem (\r
501 &IpCfgData.Ip4CfgData.StationAddress,\r
502 &CfgData->Tcp4CfgData.AccessPoint.StationAddress,\r
503 sizeof (EFI_IPv4_ADDRESS)\r
504 );\r
505\r
506 } else {\r
507 ASSERT (Sk->IpVersion == IP_VERSION_6);\r
508\r
509 CopyMem (&IpCfgData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA));\r
510 IpCfgData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
511 IpCfgData.Ip6CfgData.TrafficClass = CfgData->Tcp6CfgData.TrafficClass;\r
512 IpCfgData.Ip6CfgData.HopLimit = CfgData->Tcp6CfgData.HopLimit;\r
513 IpCfgData.Ip6CfgData.ReceiveTimeout = (UINT32) (-1);\r
514 IP6_COPY_ADDRESS (\r
515 &IpCfgData.Ip6CfgData.StationAddress,\r
516 &CfgData->Tcp6CfgData.AccessPoint.StationAddress\r
517 );\r
518 IP6_COPY_ADDRESS (\r
519 &IpCfgData.Ip6CfgData.DestinationAddress,\r
520 &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress\r
521 );\r
522 }\r
523\r
524 //\r
525 // Configure the IP instance this Tcb consumes.\r
526 //\r
527 Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);\r
528 if (EFI_ERROR (Status)) {\r
529 goto OnExit;\r
530 }\r
531\r
532 if (Sk->IpVersion == IP_VERSION_4) {\r
533 //\r
534 // Get the default address information if the instance is configured to use default address.\r
535 //\r
536 CfgData->Tcp4CfgData.AccessPoint.StationAddress = IpCfgData.Ip4CfgData.StationAddress;\r
537 CfgData->Tcp4CfgData.AccessPoint.SubnetMask = IpCfgData.Ip4CfgData.SubnetMask;\r
538\r
539 TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp4CfgData.AccessPoint;\r
540 } else {\r
541 IP6_COPY_ADDRESS (\r
542 &CfgData->Tcp6CfgData.AccessPoint.StationAddress,\r
543 &IpCfgData.Ip6CfgData.StationAddress\r
544 );\r
545\r
546 TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp6CfgData.AccessPoint;\r
547 }\r
548\r
549 //\r
550 // check if we can bind this endpoint in CfgData\r
551 //\r
552 Status = TcpBind (TcpAp, Sk->IpVersion);\r
553\r
554 if (EFI_ERROR (Status)) {\r
555 DEBUG (\r
556 (EFI_D_ERROR,\r
557 "TcpConfigurePcb: Bind endpoint failed with %r\n",\r
558 Status)\r
559 );\r
560\r
561 goto OnExit;\r
562 }\r
563\r
564 //\r
565 // Initalize the operating information in this Tcb\r
566 //\r
567 ASSERT (Tcb->State == TCP_CLOSED &&\r
568 IsListEmpty (&Tcb->SndQue) &&\r
569 IsListEmpty (&Tcb->RcvQue));\r
570\r
571 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
572 Tcb->State = TCP_CLOSED;\r
573\r
574 Tcb->SndMss = 536;\r
575 Tcb->RcvMss = TcpGetRcvMss (Sk);\r
576\r
577 Tcb->SRtt = 0;\r
578 Tcb->Rto = 3 * TCP_TICK_HZ;\r
579\r
580 Tcb->CWnd = Tcb->SndMss;\r
581 Tcb->Ssthresh = 0xffffffff;\r
582\r
583 Tcb->CongestState = TCP_CONGEST_OPEN;\r
584\r
585 Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;\r
586 Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;\r
587 Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;\r
588 Tcb->MaxRexmit = TCP_MAX_LOSS;\r
589 Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;\r
590 Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;\r
591 Tcb->ConnectTimeout = TCP_CONNECT_TIME;\r
592\r
593 if (Sk->IpVersion == IP_VERSION_4) {\r
594 //\r
595 // initialize Tcb in the light of CfgData\r
596 //\r
597 Tcb->Ttl = CfgData->Tcp4CfgData.TimeToLive;\r
598 Tcb->Tos = CfgData->Tcp4CfgData.TypeOfService;\r
599\r
600 Tcb->UseDefaultAddr = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;\r
601\r
602 CopyMem (&Tcb->LocalEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
603 Tcb->LocalEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.StationPort);\r
604 Tcb->SubnetMask = CfgData->Tcp4CfgData.AccessPoint.SubnetMask;\r
605\r
606 CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
607 Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.RemotePort);\r
608\r
609 Option = CfgData->Tcp4CfgData.ControlOption;\r
610 } else {\r
611 Tcb->Ttl = CfgData->Tcp6CfgData.HopLimit;\r
612 Tcb->Tos = CfgData->Tcp6CfgData.TrafficClass;\r
613\r
614 IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.StationAddress);\r
615 Tcb->LocalEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.StationPort);\r
616\r
617 IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress);\r
618 Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.RemotePort);\r
619\r
620 //\r
621 // Type EFI_TCP4_OPTION and EFI_TCP6_OPTION are the same.\r
622 //\r
623 Option = (EFI_TCP4_OPTION *) CfgData->Tcp6CfgData.ControlOption;\r
624 }\r
625\r
626 if (Option != NULL) {\r
627 SET_RCV_BUFFSIZE (\r
628 Sk,\r
629 (UINT32) (TCP_COMP_VAL (\r
630 TCP_RCV_BUF_SIZE_MIN,\r
631 TCP_RCV_BUF_SIZE,\r
632 TCP_RCV_BUF_SIZE,\r
633 Option->ReceiveBufferSize\r
634 )\r
635 )\r
636 );\r
637 SET_SND_BUFFSIZE (\r
638 Sk,\r
639 (UINT32) (TCP_COMP_VAL (\r
640 TCP_SND_BUF_SIZE_MIN,\r
641 TCP_SND_BUF_SIZE,\r
642 TCP_SND_BUF_SIZE,\r
643 Option->SendBufferSize\r
644 )\r
645 )\r
646 );\r
647\r
648 SET_BACKLOG (\r
649 Sk,\r
650 (UINT32) (TCP_COMP_VAL (\r
651 TCP_BACKLOG_MIN,\r
652 TCP_BACKLOG,\r
653 TCP_BACKLOG,\r
654 Option->MaxSynBackLog\r
655 )\r
656 )\r
657 );\r
658\r
659 Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (\r
660 TCP_MAX_LOSS_MIN,\r
661 TCP_MAX_LOSS,\r
662 TCP_MAX_LOSS,\r
663 Option->DataRetries\r
664 );\r
665 Tcb->FinWait2Timeout = TCP_COMP_VAL (\r
666 TCP_FIN_WAIT2_TIME,\r
667 TCP_FIN_WAIT2_TIME_MAX,\r
668 TCP_FIN_WAIT2_TIME,\r
669 (UINT32) (Option->FinTimeout * TCP_TICK_HZ)\r
670 );\r
671\r
672 if (Option->TimeWaitTimeout != 0) {\r
673 Tcb->TimeWaitTimeout = TCP_COMP_VAL (\r
674 TCP_TIME_WAIT_TIME,\r
675 TCP_TIME_WAIT_TIME_MAX,\r
676 TCP_TIME_WAIT_TIME,\r
677 (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)\r
678 );\r
679 } else {\r
680 Tcb->TimeWaitTimeout = 0;\r
681 }\r
682\r
683 if (Option->KeepAliveProbes != 0) {\r
684 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
685\r
686 Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (\r
687 TCP_MAX_KEEPALIVE_MIN,\r
688 TCP_MAX_KEEPALIVE,\r
689 TCP_MAX_KEEPALIVE,\r
690 Option->KeepAliveProbes\r
691 );\r
692 Tcb->KeepAliveIdle = TCP_COMP_VAL (\r
693 TCP_KEEPALIVE_IDLE_MIN,\r
694 TCP_KEEPALIVE_IDLE_MAX,\r
695 TCP_KEEPALIVE_IDLE_MIN,\r
696 (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)\r
697 );\r
698 Tcb->KeepAlivePeriod = TCP_COMP_VAL (\r
699 TCP_KEEPALIVE_PERIOD_MIN,\r
700 TCP_KEEPALIVE_PERIOD,\r
701 TCP_KEEPALIVE_PERIOD,\r
702 (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)\r
703 );\r
704 }\r
705\r
706 Tcb->ConnectTimeout = TCP_COMP_VAL (\r
707 TCP_CONNECT_TIME_MIN,\r
708 TCP_CONNECT_TIME,\r
709 TCP_CONNECT_TIME,\r
710 (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)\r
711 );\r
712\r
713 if (!Option->EnableNagle) {\r
714 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);\r
715 }\r
716\r
717 if (!Option->EnableTimeStamp) {\r
718 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);\r
719 }\r
720\r
721 if (!Option->EnableWindowScaling) {\r
722 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);\r
723 }\r
724 }\r
725\r
726 //\r
727 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is\r
728 // determined, construct the IP device path and install it.\r
729 //\r
730 Status = TcpInstallDevicePath (Sk);\r
731 if (EFI_ERROR (Status)) {\r
732 goto OnExit;\r
733 }\r
734\r
735 //\r
736 // update state of Tcb and socket\r
737 //\r
738 if (((Sk->IpVersion == IP_VERSION_4) && !CfgData->Tcp4CfgData.AccessPoint.ActiveFlag) ||\r
739 ((Sk->IpVersion == IP_VERSION_6) && !CfgData->Tcp6CfgData.AccessPoint.ActiveFlag)\r
740 ) {\r
741\r
742 TcpSetState (Tcb, TCP_LISTEN);\r
743 SockSetState (Sk, SO_LISTENING);\r
744\r
745 Sk->ConfigureState = SO_CONFIGURED_PASSIVE;\r
746 } else {\r
747\r
748 Sk->ConfigureState = SO_CONFIGURED_ACTIVE;\r
749 }\r
750\r
751 if (Sk->IpVersion == IP_VERSION_6) {\r
752 Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;\r
9119637c 753\r
754 if (NetIp6IsUnspecifiedAddr (&Tcb->RemoteEnd.Ip.v6)) {\r
755 Tcb->RemoteIpZero = TRUE;\r
756 }\r
a3bcde70
HT
757 }\r
758\r
759 TcpInsertTcb (Tcb);\r
760\r
761OnExit:\r
762\r
763 return Status;\r
764}\r
765\r
766/**\r
767 The procotol handler provided to the socket layer, which is used to\r
768 dispatch the socket level requests by calling the corresponding\r
769 TCP layer functions.\r
770\r
771 @param[in] Sock Pointer to the socket of this TCP instance.\r
772 @param[in] Request The code of this operation request.\r
773 @param[in] Data Pointer to the operation specific data passed in\r
774 together with the operation request. This is an\r
775 optional parameter that may be NULL.\r
776\r
777 @retval EFI_SUCCESS The socket request completed successfully.\r
778 @retval other The error status returned by the corresponding TCP\r
779 layer function.\r
780\r
781**/\r
782EFI_STATUS\r
783TcpDispatcher (\r
784 IN SOCKET *Sock,\r
785 IN UINT8 Request,\r
786 IN VOID *Data OPTIONAL\r
787 )\r
788{\r
789 TCP_CB *Tcb;\r
790 TCP_PROTO_DATA *ProtoData;\r
791\r
792 ProtoData = (TCP_PROTO_DATA *) Sock->ProtoReserved;\r
793 Tcb = ProtoData->TcpPcb;\r
794\r
795 switch (Request) {\r
796 case SOCK_POLL:\r
797 if (Tcb->Sk->IpVersion == IP_VERSION_4) {\r
798 ProtoData->TcpService->IpIo->Ip.Ip4->Poll (ProtoData->TcpService->IpIo->Ip.Ip4);\r
799 } else {\r
800 ProtoData->TcpService->IpIo->Ip.Ip6->Poll (ProtoData->TcpService->IpIo->Ip.Ip6);\r
801 }\r
802\r
803 break;\r
804\r
805 case SOCK_CONSUMED:\r
806 //\r
807 // After user received data from socket buffer, socket will\r
808 // notify TCP using this message to give it a chance to send out\r
809 // window update information\r
810 //\r
811 ASSERT (Tcb != NULL);\r
812 TcpOnAppConsume (Tcb);\r
813 break;\r
814\r
815 case SOCK_SND:\r
816\r
817 ASSERT (Tcb != NULL);\r
818 TcpOnAppSend (Tcb);\r
819 break;\r
820\r
821 case SOCK_CLOSE:\r
822\r
823 TcpOnAppClose (Tcb);\r
824\r
825 break;\r
826\r
827 case SOCK_ABORT:\r
828\r
829 TcpOnAppAbort (Tcb);\r
830\r
831 break;\r
832\r
833 case SOCK_SNDPUSH:\r
834 Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);\r
835 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);\r
836\r
837 break;\r
838\r
839 case SOCK_SNDURG:\r
840 Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;\r
841 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);\r
842\r
843 break;\r
844\r
845 case SOCK_CONNECT:\r
846\r
847 TcpOnAppConnect (Tcb);\r
848\r
849 break;\r
850\r
851 case SOCK_ATTACH:\r
852\r
853 return TcpAttachPcb (Sock);\r
854\r
855 break;\r
856\r
857 case SOCK_FLUSH:\r
858\r
859 TcpFlushPcb (Tcb);\r
860\r
861 break;\r
862\r
863 case SOCK_DETACH:\r
864\r
865 TcpDetachPcb (Sock);\r
866\r
867 break;\r
868\r
869 case SOCK_CONFIGURE:\r
870\r
871 return TcpConfigurePcb (\r
872 Sock,\r
873 (TCP_CONFIG_DATA *) Data\r
874 );\r
875\r
876 break;\r
877\r
878 case SOCK_MODE:\r
879\r
880 ASSERT ((Data != NULL) && (Tcb != NULL));\r
881\r
882 if (Tcb->Sk->IpVersion == IP_VERSION_4) {\r
883\r
884 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);\r
885 } else {\r
886\r
887 return Tcp6GetMode (Tcb, (TCP6_MODE_DATA *) Data);\r
888 }\r
889\r
890 break;\r
891\r
892 case SOCK_ROUTE:\r
893\r
894 ASSERT ((Data != NULL) && (Tcb != NULL) && (Tcb->Sk->IpVersion == IP_VERSION_4));\r
895\r
896 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);\r
897\r
898 default:\r
899\r
900 return EFI_UNSUPPORTED;\r
901 }\r
902\r
903 return EFI_SUCCESS;\r
904}\r