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