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