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