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