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