3 Copyright (c) 2005 - 2006, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
21 #include "Tcp4Main.h"
\r
23 #define TCP_COMP_VAL(Min, Max, Default, Val) \
\r
24 ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
\r
30 IN TCP4_ROUTE_INFO *RouteInfo
\r
34 Routine Description:
\r
36 Add or remove a route entry in the IP route table associated
\r
37 with this TCP instance.
\r
41 Tcb - Pointer to the TCP_CB of this TCP instance.
\r
42 RouteInfo - Pointer to the route info to be processed.
\r
46 EFI_SUCCESS - The operation completed successfully.
\r
47 EFI_NOT_STARTED - The driver instance has not been started.
\r
48 EFI_NO_MAPPING - When using the default address, configuration(DHCP,
\r
49 BOOTP, RARP, etc.) is not finished yet.
\r
50 EFI_OUT_OF_RESOURCES - Could not add the entry to the routing table.
\r
51 EFI_NOT_FOUND - This route is not in the routing table
\r
52 (when RouteInfo->DeleteRoute is TRUE).
\r
53 EFI_ACCESS_DENIED - The route is already defined in the routing table
\r
54 (when RouteInfo->DeleteRoute is FALSE).
\r
58 EFI_IP4_PROTOCOL *Ip;
\r
60 Ip = Tcb->IpInfo->Ip;
\r
66 RouteInfo->DeleteRoute,
\r
67 RouteInfo->SubnetAddress,
\r
68 RouteInfo->SubnetMask,
\r
69 RouteInfo->GatewayAddress
\r
76 Get the operational settings of this TCP instance.
\r
78 @param Tcb Pointer to the TCP_CB of this TCP instance.
\r
79 @param Mode Pointer to the buffer to store the operational
\r
82 @retval EFI_SUCCESS The mode data is read.
\r
83 @retval EFI_NOT_STARTED No configuration data is available because this
\r
84 instance hasn't been started.
\r
91 IN TCP4_MODE_DATA *Mode
\r
95 EFI_TCP4_CONFIG_DATA *ConfigData;
\r
96 EFI_TCP4_ACCESS_POINT *AccessPoint;
\r
97 EFI_TCP4_OPTION *Option;
\r
98 EFI_IP4_PROTOCOL *Ip;
\r
102 if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
\r
103 return EFI_NOT_STARTED;
\r
106 if (Mode->Tcp4State) {
\r
107 *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;
\r
110 if (Mode->Tcp4ConfigData) {
\r
112 ConfigData = Mode->Tcp4ConfigData;
\r
113 AccessPoint = &(ConfigData->AccessPoint);
\r
114 Option = ConfigData->ControlOption;
\r
116 ConfigData->TypeOfService = Tcb->TOS;
\r
117 ConfigData->TimeToLive = Tcb->TTL;
\r
119 AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
\r
121 NetCopyMem (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
\r
122 AccessPoint->SubnetMask = Tcb->SubnetMask;
\r
123 AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
\r
125 NetCopyMem (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
\r
126 AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
\r
127 AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
\r
129 if (Option != NULL) {
\r
130 Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
\r
131 Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
\r
132 Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
\r
134 Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
\r
135 Option->DataRetries = Tcb->MaxRexmit;
\r
136 Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
\r
137 Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
\r
138 Option->KeepAliveProbes = Tcb->MaxKeepAlive;
\r
139 Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
\r
140 Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
\r
142 Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
\r
143 Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
\r
144 Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS))
\r
147 Option->EnableSelectiveAck = FALSE;
\r
148 Option->EnablePathMtuDiscovery = FALSE;
\r
152 Ip = Tcb->IpInfo->Ip;
\r
155 return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
\r
160 If AP->StationPort isn't zero, check whether the access point
\r
161 is registered, else generate a random station port for this
\r
164 @param AP Pointer to the access point.
\r
166 @retval EFI_SUCCESS The check is passed or the port is assigned.
\r
167 @retval EFI_INVALID_PARAMETER The non-zero station port is already used.
\r
168 @retval EFI_OUT_OF_RESOURCES No port can be allocated.
\r
174 IN EFI_TCP4_ACCESS_POINT *AP
\r
179 if (0 != AP->StationPort) {
\r
181 // check if a same endpoint is bound
\r
183 if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
\r
185 return EFI_INVALID_PARAMETER;
\r
189 // generate a random port
\r
193 if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
\r
194 mTcp4RandomPort = TCP4_PORT_KNOWN;
\r
199 while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
\r
203 if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
\r
206 TCP4_DEBUG_ERROR (("Tcp4Bind: no port can be allocated "
\r
207 "for this pcb\n"));
\r
209 return EFI_OUT_OF_RESOURCES;
\r
212 mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
\r
219 AP->StationPort = mTcp4RandomPort;
\r
222 return EFI_SUCCESS;
\r
227 Flush the Tcb add its associated protocols..
\r
229 @param Tcb Pointer to the TCP_CB to be flushed.
\r
231 @retval EFI_SUCCESS The operation is completed successfully.
\r
241 TCP4_PROTO_DATA *TcpProto;
\r
243 IpIoConfigIp (Tcb->IpInfo, NULL);
\r
246 TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
\r
248 if (SOCK_IS_CONFIGURED (Sock)) {
\r
249 NetListRemoveEntry (&Tcb->List);
\r
252 // Uninstall the device path protocl.
\r
254 gBS->UninstallProtocolInterface (
\r
256 &gEfiDevicePathProtocolGuid,
\r
259 NetFreePool (Sock->DevicePath);
\r
261 TcpSetVariableData (TcpProto->TcpService);
\r
264 NetbufFreeList (&Tcb->SndQue);
\r
265 NetbufFreeList (&Tcb->RcvQue);
\r
275 TCP4_PROTO_DATA *ProtoData;
\r
278 Tcb = NetAllocateZeroPool (sizeof (TCP_CB));
\r
282 TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: failed to allocate a TCB\n"));
\r
284 return EFI_OUT_OF_RESOURCES;
\r
287 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
\r
288 IpIo = ProtoData->TcpService->IpIo;
\r
291 // Create an IpInfo for this Tcb.
\r
293 Tcb->IpInfo = IpIoAddIp (IpIo);
\r
294 if (Tcb->IpInfo == NULL) {
\r
297 return EFI_OUT_OF_RESOURCES;
\r
300 NetListInit (&Tcb->List);
\r
301 NetListInit (&Tcb->SndQue);
\r
302 NetListInit (&Tcb->RcvQue);
\r
304 Tcb->State = TCP_CLOSED;
\r
306 ProtoData->TcpPcb = Tcb;
\r
308 return EFI_SUCCESS;
\r
317 TCP4_PROTO_DATA *ProtoData;
\r
320 ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
\r
321 Tcb = ProtoData->TcpPcb;
\r
323 ASSERT (Tcb != NULL);
\r
325 Tcp4FlushPcb (Tcb);
\r
327 IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
\r
331 ProtoData->TcpPcb = NULL;
\r
336 Configure the Tcb using CfgData.
\r
338 @param Sk Pointer to the socket of this TCP instance.
\r
339 @param SkTcb Pointer to the TCP_CB of this TCP instance.
\r
340 @param CfgData Pointer to the TCP configuration data.
\r
342 @retval EFI_SUCCESS The operation is completed successfully.
\r
343 @retval EFI_INVALID_PARAMETER A same access point has been configured in
\r
344 another TCP instance.
\r
345 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
\r
352 IN EFI_TCP4_CONFIG_DATA *CfgData
\r
355 EFI_IP4_CONFIG_DATA IpCfgData;
\r
357 EFI_TCP4_OPTION *Option;
\r
358 TCP4_PROTO_DATA *TcpProto;
\r
361 ASSERT (CfgData && Sk && Sk->SockHandle);
\r
363 TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
\r
364 Tcb = TcpProto->TcpPcb;
\r
366 ASSERT (Tcb != NULL);
\r
369 // Add Ip for send pkt to the peer
\r
371 CopyMem (&IpCfgData, &mIpIoDefaultIpConfigData, sizeof (IpCfgData));
\r
372 IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
\r
373 IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
\r
374 IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
\r
375 IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
\r
376 IpCfgData.ReceiveTimeout = (UINT32) (-1);
\r
379 // Configure the IP instance this Tcb consumes.
\r
381 Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
\r
382 if (EFI_ERROR (Status)) {
\r
387 // Get the default address info if the instance is configured to use default address.
\r
389 if (CfgData->AccessPoint.UseDefaultAddress) {
\r
390 CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
\r
391 CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
\r
395 // check if we can bind this endpoint in CfgData
\r
397 Status = Tcp4Bind (&(CfgData->AccessPoint));
\r
399 if (EFI_ERROR (Status)) {
\r
400 TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: Bind endpoint failed "
\r
401 "with %r\n", Status));
\r
407 // Initalize the operating information in this Tcb
\r
409 ASSERT (Tcb->State == TCP_CLOSED &&
\r
410 NetListIsEmpty (&Tcb->SndQue) &&
\r
411 NetListIsEmpty (&Tcb->RcvQue));
\r
413 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
\r
414 Tcb->State = TCP_CLOSED;
\r
417 Tcb->RcvMss = TcpGetRcvMss (Sk);
\r
420 Tcb->Rto = 3 * TCP_TICK_HZ;
\r
422 Tcb->CWnd = Tcb->SndMss;
\r
423 Tcb->Ssthresh = 0xffffffff;
\r
425 Tcb->CongestState = TCP_CONGEST_OPEN;
\r
427 Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
\r
428 Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
\r
429 Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
\r
430 Tcb->MaxRexmit = TCP_MAX_LOSS;
\r
431 Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
\r
432 Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
\r
433 Tcb->ConnectTimeout = TCP_CONNECT_TIME;
\r
436 // initialize Tcb in the light of CfgData
\r
438 Tcb->TTL = CfgData->TimeToLive;
\r
439 Tcb->TOS = CfgData->TypeOfService;
\r
441 Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;
\r
443 NetCopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
\r
444 Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
\r
445 Tcb->SubnetMask = CfgData->AccessPoint.SubnetMask;
\r
447 if (CfgData->AccessPoint.ActiveFlag) {
\r
448 NetCopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
\r
449 Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
\r
451 Tcb->RemoteEnd.Ip = 0;
\r
452 Tcb->RemoteEnd.Port = 0;
\r
455 Option = CfgData->ControlOption;
\r
457 if (Option != NULL) {
\r
460 (UINT32) (TCP_COMP_VAL (
\r
461 TCP_RCV_BUF_SIZE_MIN,
\r
464 Option->ReceiveBufferSize
\r
470 (UINT32) (TCP_COMP_VAL (
\r
471 TCP_SND_BUF_SIZE_MIN,
\r
474 Option->SendBufferSize
\r
481 (UINT32) (TCP_COMP_VAL (
\r
485 Option->MaxSynBackLog
\r
490 Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
\r
494 Option->DataRetries
\r
496 Tcb->FinWait2Timeout = TCP_COMP_VAL (
\r
497 TCP_FIN_WAIT2_TIME,
\r
498 TCP_FIN_WAIT2_TIME_MAX,
\r
499 TCP_FIN_WAIT2_TIME,
\r
500 (UINT32) (Option->FinTimeout * TCP_TICK_HZ)
\r
503 if (Option->TimeWaitTimeout != 0) {
\r
504 Tcb->TimeWaitTimeout = TCP_COMP_VAL (
\r
505 TCP_TIME_WAIT_TIME,
\r
506 TCP_TIME_WAIT_TIME_MAX,
\r
507 TCP_TIME_WAIT_TIME,
\r
508 (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)
\r
511 Tcb->TimeWaitTimeout = 0;
\r
514 if (Option->KeepAliveProbes != 0) {
\r
515 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
\r
517 Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
\r
518 TCP_MAX_KEEPALIVE_MIN,
\r
521 Option->KeepAliveProbes
\r
523 Tcb->KeepAliveIdle = TCP_COMP_VAL (
\r
524 TCP_KEEPALIVE_IDLE_MIN,
\r
525 TCP_KEEPALIVE_IDLE_MAX,
\r
526 TCP_KEEPALIVE_IDLE_MIN,
\r
527 (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
\r
529 Tcb->KeepAlivePeriod = TCP_COMP_VAL (
\r
530 TCP_KEEPALIVE_PERIOD_MIN,
\r
531 TCP_KEEPALIVE_PERIOD,
\r
532 TCP_KEEPALIVE_PERIOD,
\r
533 (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
\r
537 Tcb->ConnectTimeout = TCP_COMP_VAL (
\r
538 TCP_CONNECT_TIME_MIN,
\r
541 (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
\r
544 if (Option->EnableNagle == FALSE) {
\r
545 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
\r
548 if (Option->EnableTimeStamp == FALSE) {
\r
549 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
\r
552 if (Option->EnableWindowScaling == FALSE) {
\r
553 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
\r
558 // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
\r
559 // determined, construct the IP device path and install it.
\r
561 Status = TcpInstallDevicePath (Sk);
\r
562 if (EFI_ERROR (Status)) {
\r
567 // update state of Tcb and socket
\r
569 if (CfgData->AccessPoint.ActiveFlag == FALSE) {
\r
571 TcpSetState (Tcb, TCP_LISTEN);
\r
572 SockSetState (Sk, SO_LISTENING);
\r
574 Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
\r
577 Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
\r
580 TcpInsertTcb (Tcb);
\r
589 The procotol handler provided to the socket layer, used to
\r
590 dispatch the socket level requests by calling the corresponding
\r
591 TCP layer functions.
\r
593 @param Sock Pointer to the socket of this TCP instance.
\r
594 @param Request The code of this operation request.
\r
595 @param Data Pointer to the operation specific data passed in
\r
596 together with the operation request.
\r
598 @retval EFI_SUCCESS The socket request is completed successfully.
\r
599 @retval other The error status returned by the corresponding TCP
\r
606 IN SOCK_REQUEST Request,
\r
607 IN VOID *Data OPTIONAL
\r
611 TCP4_PROTO_DATA *ProtoData;
\r
612 EFI_IP4_PROTOCOL *Ip;
\r
614 ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
\r
615 Tcb = ProtoData->TcpPcb;
\r
619 Ip = ProtoData->TcpService->IpIo->Ip;
\r
623 case SOCK_CONSUMED:
\r
625 // After user received data from socket buffer, socket will
\r
626 // notify TCP using this message to give it a chance to send out
\r
627 // window update information
\r
630 TcpOnAppConsume (Tcb);
\r
636 TcpOnAppSend (Tcb);
\r
641 TcpOnAppClose (Tcb);
\r
647 TcpOnAppAbort (Tcb);
\r
652 Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
\r
653 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
\r
658 Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
\r
659 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
\r
665 TcpOnAppConnect (Tcb);
\r
671 return Tcp4AttachPcb (Sock);
\r
677 Tcp4FlushPcb (Tcb);
\r
683 Tcp4DetachPcb (Sock);
\r
687 case SOCK_CONFIGURE:
\r
689 return Tcp4ConfigurePcb (
\r
691 (EFI_TCP4_CONFIG_DATA *) Data
\r
698 ASSERT (Data && Tcb);
\r
700 return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
\r
706 ASSERT (Data && Tcb);
\r
708 return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
\r
712 return EFI_SUCCESS;
\r