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