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