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