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