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