MdeModulePkg: Delete Tcp4Dxe in MdeModulePkg.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1278

This patch is to delete the Tcp4Dxe driver in MdeModulePkg. The driver
will not be maintained and can't co-work with the dual-stack TcpDxe in
NetworkPkg.

People should use below NetworkPkg drivers instead:
  NetworkPkg/TcpDxe/TcpDxe.inf
Which is actively maintained with more bug fixes and new feature support.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Siyuan Fu <siyuan.fu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
This commit is contained in:
Siyuan Fu 2018-12-20 09:22:06 +08:00
parent 41203b9ab5
commit 376a5dbe97
23 changed files with 0 additions and 12847 deletions

View File

@ -359,7 +359,6 @@
MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf

View File

@ -1,433 +0,0 @@
/** @file
UEFI Component Name(2) protocol implementation for Tcp4Dxe driver.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
///
/// EFI Component Name Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName = {
TcpComponentNameGetDriverName,
TcpComponentNameGetControllerName,
"eng"
};
///
/// EFI Component Name 2 Protocol
///
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) TcpComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) TcpComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {
{
"eng;en",
L"Tcp Network Service Driver"
},
{
NULL,
NULL
}
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable = NULL;
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mTcpDriverNameTable,
DriverName,
(BOOLEAN) (This == &gTcp4ComponentName)
);
}
/**
Update the component name for the Tcp4 child handle.
@param Tcp4[in] A pointer to the EFI_TCP4_PROTOCOL.
@retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
**/
EFI_STATUS
UpdateName (
IN EFI_TCP4_PROTOCOL *Tcp4
)
{
EFI_STATUS Status;
CHAR16 HandleName[80];
EFI_TCP4_CONFIG_DATA Tcp4ConfigData;
if (Tcp4 == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Format the child name into the string buffer as:
// TCPv4 (SrcPort=59, DestPort=60, ActiveFlag=TRUE)
//
ZeroMem (&Tcp4ConfigData, sizeof (Tcp4ConfigData));
Status = Tcp4->GetModeData (Tcp4, NULL, &Tcp4ConfigData, NULL, NULL, NULL);
if (!EFI_ERROR (Status)) {
UnicodeSPrint (HandleName, sizeof (HandleName),
L"TCPv4 (SrcPort=%d, DestPort=%d, ActiveFlag=%s)",
Tcp4ConfigData.AccessPoint.StationPort,
Tcp4ConfigData.AccessPoint.RemotePort,
(Tcp4ConfigData.AccessPoint.ActiveFlag ? L"TRUE" : L"FALSE")
);
} else if (Status == EFI_NOT_STARTED) {
UnicodeSPrint (
HandleName,
sizeof (HandleName),
L"TCPv4 (Not started)"
);
} else {
return Status;
}
if (gTcpControllerNameTable != NULL) {
FreeUnicodeStringTable (gTcpControllerNameTable);
gTcpControllerNameTable = NULL;
}
Status = AddUnicodeString2 (
"eng",
gTcp4ComponentName.SupportedLanguages,
&gTcpControllerNameTable,
HandleName,
TRUE
);
if (EFI_ERROR (Status)) {
return Status;
}
return AddUnicodeString2 (
"en",
gTcp4ComponentName2.SupportedLanguages,
&gTcpControllerNameTable,
HandleName,
FALSE
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] ControllerHandle The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
EFI_TCP4_PROTOCOL *Tcp4;
//
// Only provide names for child handles.
//
if (ChildHandle == NULL) {
return EFI_UNSUPPORTED;
}
//
// Make sure this driver produced ChildHandle
//
Status = EfiTestChildHandle (
ControllerHandle,
ChildHandle,
&gEfiIp4ProtocolGuid
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Retrieve an instance of a produced protocol from ChildHandle
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiTcp4ProtocolGuid,
(VOID **)&Tcp4,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Update the component name for this child handle.
//
Status = UpdateName (Tcp4);
if (EFI_ERROR (Status)) {
return Status;
}
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
gTcpControllerNameTable,
ControllerName,
(BOOLEAN)(This == &gTcp4ComponentName)
);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +0,0 @@
/** @file
Socket implementation header file.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _SOCK_IMPL_H_
#define _SOCK_IMPL_H_
#include "Socket.h"
#include "Tcp4Main.h"
/**
Signal a event with the given status.
@param Token The token's event is to be signaled.
@param TokenStatus The status to be sent with the event.
**/
#define SIGNAL_TOKEN(Token, TokenStatus) \
do { \
(Token)->Status = (TokenStatus); \
gBS->SignalEvent ((Token)->Event); \
} while (0)
/**
Supporting function for both SockImpl and SockInterface.
@param Event The Event this notify function registered to, ignored.
**/
VOID
EFIAPI
SockFreeFoo (
IN EFI_EVENT Event
);
/**
Process the TCP send data, buffer the tcp txdata and append
the buffer to socket send buffer,then try to send it.
@param Sock Pointer to the socket.
@param TcpTxData Pointer to the tcp txdata.
@retval EFI_SUCCESS The operation is completed successfully.
@retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
**/
EFI_STATUS
SockProcessTcpSndData (
IN SOCKET *Sock,
IN VOID *TcpTxData
);
/**
Copy data from socket buffer to application provided receive buffer.
@param Sock Pointer to the socket.
@param TcpRxData Pointer to the application provided receive buffer.
@param RcvdBytes The maximum length of the data can be copied.
@param IsOOB If TRUE the data is OOB, else the data is normal.
**/
VOID
SockSetTcpRxData (
IN SOCKET *Sock,
IN VOID *TcpRxData,
IN UINT32 RcvdBytes,
IN BOOLEAN IsOOB
);
/**
Get received data from the socket layer to the receive token.
@param Sock Pointer to the socket.
@param RcvToken Pointer to the application provided receive token.
@return The length of data received in this token.
**/
UINT32
SockProcessRcvToken (
IN SOCKET *Sock,
IN OUT SOCK_IO_TOKEN *RcvToken
);
/**
Flush the socket.
@param Sock Pointer to the socket.
**/
VOID
SockConnFlush (
IN OUT SOCKET *Sock
);
/**
Create a socket with initial data SockInitData.
@param SockInitData Pointer to the initial data of the socket.
@return Pointer to the newly created socket.
**/
SOCKET *
SockCreate (
IN SOCK_INIT_DATA *SockInitData
);
/**
Destroy a socket.
@param Sock Pointer to the socket.
**/
VOID
SockDestroy (
IN OUT SOCKET *Sock
);
#endif

View File

@ -1,990 +0,0 @@
/** @file
Interface function of the Socket.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "SockImpl.h"
/**
Check whether the Event is in the List.
@param List Pointer to the token list to be searched.
@param Event The event to be checked.
@retval TRUE The specific Event exists in the List.
@retval FALSE The specific Event is not in the List.
**/
BOOLEAN
SockTokenExistedInList (
IN LIST_ENTRY *List,
IN EFI_EVENT Event
)
{
LIST_ENTRY *ListEntry;
SOCK_TOKEN *SockToken;
NET_LIST_FOR_EACH (ListEntry, List) {
SockToken = NET_LIST_USER_STRUCT (
ListEntry,
SOCK_TOKEN,
TokenList
);
if (Event == SockToken->Token->Event) {
return TRUE;
}
}
return FALSE;
}
/**
Call SockTokenExistedInList() to check whether the Event is
in the related socket's lists.
@param Sock Pointer to the instance's socket.
@param Event The event to be checked.
@retval TRUE The Event exists in related socket's lists.
@retval FALSE The Event is not in related socket's lists.
**/
BOOLEAN
SockTokenExisted (
IN SOCKET *Sock,
IN EFI_EVENT Event
)
{
if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
SockTokenExistedInList (&Sock->ListenTokenList, Event)) {
return TRUE;
}
if ((Sock->ConnectionToken != NULL) &&
(Sock->ConnectionToken->Event == Event)) {
return TRUE;
}
if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
return TRUE;
}
return FALSE;
}
/**
Buffer a token into the specific list of socket Sock.
@param Sock Pointer to the instance's socket.
@param List Pointer to the list to store the token.
@param Token Pointer to the token to be buffered.
@param DataLen The data length of the buffer contained in Token.
@return Pointer to the token that wraps Token. If NULL, error condition occurred.
**/
SOCK_TOKEN *
SockBufferToken (
IN SOCKET *Sock,
IN LIST_ENTRY *List,
IN VOID *Token,
IN UINT32 DataLen
)
{
SOCK_TOKEN *SockToken;
SockToken = AllocatePool (sizeof (SOCK_TOKEN));
if (NULL == SockToken) {
DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "
"to allocate SockToken\n"));
return NULL;
}
SockToken->Sock = Sock;
SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
SockToken->RemainDataLen = DataLen;
InsertTailList (List, &SockToken->TokenList);
return SockToken;
}
/**
Destroy the socket Sock and its associated protocol control block.
@param Sock The socket to be destroyed.
@retval EFI_SUCCESS The socket Sock is destroyed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockDestroyChild (
IN SOCKET *Sock
)
{
EFI_STATUS Status;
TCP4_PROTO_DATA *ProtoData;
TCP_CB *Tcb;
VOID *SockProtocol;
ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));
if (Sock->InDestroy) {
return EFI_SUCCESS;
}
Sock->InDestroy = TRUE;
ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
Tcb = ProtoData->TcpPcb;
ASSERT (Tcb != NULL);
//
// Close the IP protocol.
//
gBS->CloseProtocol (
Tcb->IpInfo->ChildHandle,
&gEfiIp4ProtocolGuid,
ProtoData->TcpService->IpIo->Image,
Sock->SockHandle
);
if (Sock->DestroyCallback != NULL) {
Sock->DestroyCallback (Sock, Sock->Context);
}
//
// Retrieve the protocol installed on this sock
//
Status = gBS->OpenProtocol (
Sock->SockHandle,
&gEfiTcp4ProtocolGuid,
&SockProtocol,
Sock->DriverBinding,
Sock->SockHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockDestroyChild: Open protocol installed "
"on socket failed with %r\n", Status));
}
//
// Uninstall the protocol installed on this sock
// in the light of Sock->SockType
//
gBS->UninstallMultipleProtocolInterfaces (
Sock->SockHandle,
&gEfiTcp4ProtocolGuid,
SockProtocol,
NULL
);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "
"access socket failed with %r\n", Status));
return EFI_ACCESS_DENIED;
}
//
// force protocol layer to detach the PCB
//
Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"
" failed with %r\n", Status));
Sock->InDestroy = FALSE;
} else if (SOCK_IS_CONFIGURED (Sock)) {
SockConnFlush (Sock);
SockSetState (Sock, SO_CLOSED);
Sock->ConfigureState = SO_UNCONFIGURED;
}
EfiReleaseLock (&(Sock->Lock));
if (EFI_ERROR (Status)) {
return Status;
}
SockDestroy (Sock);
return EFI_SUCCESS;
}
/**
Create a socket and its associated protocol control block
with the intial data SockInitData and protocol specific
data ProtoData.
@param SockInitData Inital data to setting the socket.
@return Pointer to the newly created socket. If NULL, error condition occured.
**/
SOCKET *
SockCreateChild (
IN SOCK_INIT_DATA *SockInitData
)
{
SOCKET *Sock;
VOID *SockProtocol;
EFI_STATUS Status;
//
// create a new socket
//
Sock = SockCreate (SockInitData);
if (NULL == Sock) {
DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "
"create a new socket\n"));
return NULL;
}
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "
"access socket failed with %r\n", Status));
goto ERROR;
}
//
// inform the protocol layer to attach the socket
// with a new protocol control block
//
Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
EfiReleaseLock (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"
" attach a socket with %r\n", Status));
goto ERROR;
}
return Sock;
ERROR:
if (Sock->DestroyCallback != NULL) {
Sock->DestroyCallback (Sock, Sock->Context);
}
gBS->OpenProtocol (
Sock->SockHandle,
&gEfiTcp4ProtocolGuid,
&SockProtocol,
Sock->DriverBinding,
Sock->SockHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
//
// Uninstall the protocol installed on this sock
//
gBS->UninstallMultipleProtocolInterfaces (
Sock->SockHandle,
&gEfiTcp4ProtocolGuid,
SockProtocol,
NULL
);
SockDestroy (Sock);
return NULL;
}
/**
Configure the specific socket Sock using configuration data ConfigData.
@param Sock Pointer to the socket to be configured.
@param ConfigData Pointer to the configuration data.
@retval EFI_SUCCESS The socket is configured successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
socket is already configured.
**/
EFI_STATUS
SockConfigure (
IN SOCKET *Sock,
IN VOID *ConfigData
)
{
EFI_STATUS Status;
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "
"socket failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_CONFIGURED (Sock)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
ASSERT (Sock->State == SO_CLOSED);
Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
OnExit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Initiate a connection establishment process.
@param Sock Pointer to the socket to initiate the initate the
connection.
@param Token Pointer to the token used for the connection
operation.
@retval EFI_SUCCESS The connection is initialized successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be an active one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockConnect (
IN SOCKET *Sock,
IN VOID *Token
)
{
EFI_STATUS Status;
EFI_EVENT Event;
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "
"socket failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto OnExit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto OnExit;
}
if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
SockSetState (Sock, SO_CONNECTING);
Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
OnExit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Issue a listen token to get an existed connected network instance
or wait for a connection if there is none.
@param Sock Pointer to the socket to accept connections.
@param Token The token to accept a connection.
@retval EFI_SUCCESS Either a connection is accpeted or the Token is
buffered for further acception.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be a passive one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
**/
EFI_STATUS
SockAccept (
IN SOCKET *Sock,
IN VOID *Token
)
{
EFI_TCP4_LISTEN_TOKEN *ListenToken;
LIST_ENTRY *ListEntry;
EFI_STATUS Status;
SOCKET *Socket;
EFI_EVENT Event;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!SOCK_IS_LISTENING (Sock)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
//
// Check if a connection has already in this Sock->ConnectionList
//
NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
if (SOCK_IS_CONNECTED (Socket)) {
ListenToken->NewChildHandle = Socket->SockHandle;
SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
RemoveEntryList (ListEntry);
ASSERT (Socket->Parent != NULL);
Socket->Parent->ConnCnt--;
DEBUG (
(EFI_D_NET,
"SockAccept: Accept a socket, now conncount is %d",
Socket->Parent->ConnCnt)
);
Socket->Parent = NULL;
goto Exit;
}
}
//
// Buffer this token for latter incoming connection request
//
if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
Status = EFI_OUT_OF_RESOURCES;
}
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Issue a token with data to the socket to send out.
@param Sock Pointer to the socket to process the token with
data.
@param Token The token with data that needs to send out.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockSend (
IN SOCKET *Sock,
IN VOID *Token
)
{
SOCK_IO_TOKEN *SndToken;
EFI_EVENT Event;
UINT32 FreeSpace;
EFI_TCP4_TRANSMIT_DATA *TxData;
EFI_STATUS Status;
SOCK_TOKEN *SockToken;
UINT32 DataLen;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
SndToken = (SOCK_IO_TOKEN *) Token;
TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
//
// check if a token is already in the token buffer
//
Event = SndToken->Token.Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
DataLen = (UINT32) TxData->DataLength;
//
// process this sending token now or buffer it only?
//
FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
SockToken = SockBufferToken (
Sock,
&Sock->SndTokenList,
SndToken,
DataLen
);
if (NULL == SockToken) {
Status = EFI_OUT_OF_RESOURCES;
}
} else {
SockToken = SockBufferToken (
Sock,
&Sock->ProcessingSndTokenList,
SndToken,
DataLen
);
if (NULL == SockToken) {
DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"
" socket processing SndToken List\n", Status));
Status = EFI_OUT_OF_RESOURCES;
goto Exit;
}
Status = SockProcessTcpSndData (Sock, TxData);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "
"Snd Data\n", Status));
RemoveEntryList (&(SockToken->TokenList));
FreePool (SockToken);
}
}
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Issue a token to get data from the socket.
@param Sock Pointer to the socket to get data from.
@param Token The token to store the received data from the
socket.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockRcv (
IN SOCKET *Sock,
IN VOID *Token
)
{
SOCK_IO_TOKEN *RcvToken;
UINT32 RcvdBytes;
EFI_STATUS Status;
EFI_EVENT Event;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
RcvToken = (SOCK_IO_TOKEN *) Token;
//
// check if a token is already in the token buffer of this socket
//
Event = RcvToken->Token.Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
RcvToken = (SOCK_IO_TOKEN *) Token;
RcvdBytes = GET_RCV_DATASIZE (Sock);
//
// check whether an error has happened before
//
if (EFI_ABORTED != Sock->SockError) {
SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
Sock->SockError = EFI_ABORTED;
goto Exit;
}
//
// check whether can not receive and there is no any
// data buffered in Sock->RcvBuffer
//
if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
Status = EFI_CONNECTION_FIN;
goto Exit;
}
if (RcvdBytes != 0) {
SockProcessRcvToken (Sock, RcvToken);
Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
} else {
if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
Status = EFI_OUT_OF_RESOURCES;
}
}
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Reset the socket and its associated protocol control block.
@param Sock Pointer to the socket to be flushed.
@retval EFI_SUCCESS The socket is flushed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockFlush (
IN SOCKET *Sock
)
{
EFI_STATUS Status;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (!SOCK_IS_CONFIGURED (Sock)) {
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"
" SOCK_FLUSH with %r", Status));
goto Exit;
}
SOCK_ERROR (Sock, EFI_ABORTED);
SockConnFlush (Sock);
SockSetState (Sock, SO_CLOSED);
Sock->ConfigureState = SO_UNCONFIGURED;
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Close or abort the socket associated connection.
@param Sock Pointer to the socket of the connection to close or
abort.
@param Token The token for close operation.
@param OnAbort TRUE for aborting the connection, FALSE to close it.
@retval EFI_SUCCESS The close or abort operation is initialized
successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockClose (
IN SOCKET *Sock,
IN VOID *Token,
IN BOOLEAN OnAbort
)
{
EFI_STATUS Status;
EFI_EVENT Event;
ASSERT (SockStream == Sock->Type);
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (SOCK_IS_DISCONNECTING (Sock)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Sock->CloseToken = Token;
SockSetState (Sock, SO_DISCONNECTING);
if (OnAbort) {
Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
} else {
Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
}
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}
/**
Get the mode data of the low layer protocol.
@param Sock Pointer to the socket to get mode data from.
@param Mode Pointer to the data to store the low layer mode
information.
@retval EFI_SUCCESS The mode data is got successfully.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockGetMode (
IN SOCKET *Sock,
IN OUT VOID *Mode
)
{
return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
}
/**
Add or remove route information in IP route table associated
with this socket.
@param Sock Pointer to the socket associated with the IP route
table to operate on.
@param RouteInfo Pointer to the route information to be processed.
@retval EFI_SUCCESS The route table is updated successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockRoute (
IN SOCKET *Sock,
IN VOID *RouteInfo
)
{
EFI_STATUS Status;
Status = EfiAcquireLockOrFail (&(Sock->Lock));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
Exit:
EfiReleaseLock (&(Sock->Lock));
return Status;
}

View File

@ -1,954 +0,0 @@
/** @file
Socket header file.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <Uefi.h>
#include <Protocol/Ip4.h>
#include <Protocol/Tcp4.h>
#include <Protocol/Udp4.h>
#include <Library/NetLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/DpcLib.h>
#include <Library/PrintLib.h>
#define SOCK_SND_BUF 0
#define SOCK_RCV_BUF 1
#define SOCK_BUFF_LOW_WATER (2 * 1024)
#define SOCK_RCV_BUFF_SIZE (8 * 1024)
#define SOCK_SND_BUFF_SIZE (8 * 1024)
#define SOCK_BACKLOG 5
#define PROTO_RESERVED_LEN 20
#define SO_NO_MORE_DATA 0x0001
//
//
//
// When a socket is created it enters into SO_UNCONFIGURED,
// no actions can be taken on this socket, only after calling
// SockConfigure. The state transition diagram of socket is
// as following:
//
// SO_UNCONFIGURED --- SO_CONFIGURED --- SO_CONNECTING
// ^ | |
// | ---> SO_LISTENING |
// | |
// |------------------SO_DISCONNECTING<-- SO_CONNECTED
//
// A passive socket can only go into SO_LISTENING and
// SO_UNCONFIGURED state. SO_XXXING state is a middle state
// when a socket is undergoing a protocol procedure such
// as requesting a TCP connection.
//
//
//
///
/// Socket state
///
#define SO_CLOSED 0
#define SO_LISTENING 1
#define SO_CONNECTING 2
#define SO_CONNECTED 3
#define SO_DISCONNECTING 4
///
/// Socket configure state
///
#define SO_UNCONFIGURED 0
#define SO_CONFIGURED_ACTIVE 1
#define SO_CONFIGURED_PASSIVE 2
#define SO_NO_MAPPING 3
/**
Set socket SO_NO_MORE_DATA flag.
@param Sock Pointer to the socket
**/
#define SOCK_NO_MORE_DATA(Sock) ((Sock)->Flag |= SO_NO_MORE_DATA)
/**
Check whether the socket is unconfigured.
@param Sock Pointer to the socket
@retval True The socket is unconfigued
@retval False The socket is not unconfigued
**/
#define SOCK_IS_UNCONFIGURED(Sock) ((Sock)->ConfigureState == SO_UNCONFIGURED)
/**
Check whether the socket is configured.
@param Sock Pointer to the socket
@retval True The socket is configued
@retval False The socket is not configued
**/
#define SOCK_IS_CONFIGURED(Sock) \
(((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE) || \
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE))
/**
Check whether the socket is configured to active mode.
@param Sock Pointer to the socket
@retval True The socket is configued to active mode
@retval False The socket is not configued to active mode
**/
#define SOCK_IS_CONFIGURED_ACTIVE(Sock) \
((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE)
/**
Check whether the socket is configured to passive mode.
@param Sock Pointer to the socket
@retval True The socket is configued to passive mode
@retval False The socket is not configued to passive mode
**/
#define SOCK_IS_CONNECTED_PASSIVE(Sock) \
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE)
/**
Check whether the socket is mapped.
@param Sock Pointer to the socket
@retval True The socket is no mapping
@retval False The socket is mapped
**/
#define SOCK_IS_NO_MAPPING(Sock) \
((Sock)->ConfigureState == SO_NO_MAPPING)
/**
Check whether the socket is closed.
@param Sock Pointer to the socket
@retval True The socket is closed
@retval False The socket is not closed
**/
#define SOCK_IS_CLOSED(Sock) ((Sock)->State == SO_CLOSED)
/**
Check whether the socket is listening.
@param Sock Pointer to the socket
@retval True The socket is listening
@retval False The socket is not listening
**/
#define SOCK_IS_LISTENING(Sock) ((Sock)->State == SO_LISTENING)
/**
Check whether the socket is connecting.
@param Sock Pointer to the socket
@retval True The socket is connecting
@retval False The socket is not connecting
**/
#define SOCK_IS_CONNECTING(Sock) ((Sock)->State == SO_CONNECTING)
/**
Check whether the socket has connected.
@param Sock Pointer to the socket
@retval True The socket has connected
@retval False The socket has not connected
**/
#define SOCK_IS_CONNECTED(Sock) ((Sock)->State == SO_CONNECTED)
/**
Check whether the socket is disconnecting.
@param Sock Pointer to the socket
@retval True The socket is disconnecting
@retval False The socket is not disconnecting
**/
#define SOCK_IS_DISCONNECTING(Sock) ((Sock)->State == SO_DISCONNECTING)
/**
Check whether the socket is no more data.
@param Sock Pointer to the socket
@retval True The socket is no more data
@retval False The socket still has data
**/
#define SOCK_IS_NO_MORE_DATA(Sock) (0 != ((Sock)->Flag & SO_NO_MORE_DATA))
/**
Set the size of the receive buffer.
@param Sock Pointer to the socket
@param Size The size to set
**/
#define SET_RCV_BUFFSIZE(Sock, Size) ((Sock)->RcvBuffer.HighWater = (Size))
/**
Get the size of the receive buffer.
@param Sock Pointer to the socket
@return The receive buffer size
**/
#define GET_RCV_BUFFSIZE(Sock) ((Sock)->RcvBuffer.HighWater)
/**
Get the size of the receive data.
@param Sock Pointer to the socket
@return The received data size
**/
#define GET_RCV_DATASIZE(Sock) (((Sock)->RcvBuffer.DataQueue)->BufSize)
/**
Set the size of the send buffer.
@param Sock Pointer to the socket
@param Size The size to set
**/
#define SET_SND_BUFFSIZE(Sock, Size) ((Sock)->SndBuffer.HighWater = (Size))
/**
Get the size of the send buffer.
@param Sock Pointer to the socket
@return The send buffer size
**/
#define GET_SND_BUFFSIZE(Sock) ((Sock)->SndBuffer.HighWater)
/**
Get the size of the send data.
@param Sock Pointer to the socket
@return The send data size
**/
#define GET_SND_DATASIZE(Sock) (((Sock)->SndBuffer.DataQueue)->BufSize)
/**
Set the backlog value of the socket.
@param Sock Pointer to the socket
@param Value The value to set
**/
#define SET_BACKLOG(Sock, Value) ((Sock)->BackLog = (Value))
/**
Get the backlog value of the socket.
@param Sock Pointer to the socket
@return The backlog value
**/
#define GET_BACKLOG(Sock) ((Sock)->BackLog)
/**
Set the socket with error state.
@param Sock Pointer to the socket
@param Error The error state
**/
#define SOCK_ERROR(Sock, Error) ((Sock)->SockError = (Error))
#define SND_BUF_HDR_LEN(Sock) \
((SockBufFirst (&((Sock)->SndBuffer)))->TotalSize)
#define RCV_BUF_HDR_LEN(Sock) \
((SockBufFirst (&((Sock)->RcvBuffer)))->TotalSize)
#define SOCK_SIGNATURE SIGNATURE_32 ('S', 'O', 'C', 'K')
#define SOCK_FROM_THIS(a) CR ((a), SOCKET, NetProtocol, SOCK_SIGNATURE)
#define SOCK_FROM_TOKEN(Token) (((SOCK_TOKEN *) (Token))->Sock)
#define PROTO_TOKEN_FORM_SOCK(SockToken, Type) \
((Type *) (((SOCK_TOKEN *) (SockToken))->Token))
typedef struct _SOCKET SOCKET;
///
/// Socket completion token
///
typedef struct _SOCK_COMPLETION_TOKEN {
EFI_EVENT Event; ///< The event to be issued
EFI_STATUS Status; ///< The status to be issued
} SOCK_COMPLETION_TOKEN;
typedef union {
VOID *RxData;
VOID *TxData;
} SOCK_IO_DATA;
///
/// The application token with data packet
///
typedef struct _SOCK_IO_TOKEN {
SOCK_COMPLETION_TOKEN Token;
SOCK_IO_DATA Packet;
} SOCK_IO_TOKEN;
///
/// The request issued from socket layer to protocol layer.
///
#define SOCK_ATTACH 0 ///< Attach current socket to a new PCB
#define SOCK_DETACH 1 ///< Detach current socket from the PCB
#define SOCK_CONFIGURE 2 ///< Configure attached PCB
#define SOCK_FLUSH 3 ///< Flush attached PCB
#define SOCK_SND 4 ///< Need protocol to send something
#define SOCK_SNDPUSH 5 ///< Need protocol to send pushed data
#define SOCK_SNDURG 6 ///< Need protocol to send urgent data
#define SOCK_CONSUMED 7 ///< Application has retrieved data from socket
#define SOCK_CONNECT 8 ///< Need to connect to a peer
#define SOCK_CLOSE 9 ///< Need to close the protocol process
#define SOCK_ABORT 10 ///< Need to reset the protocol process
#define SOCK_POLL 11 ///< Need to poll to the protocol layer
#define SOCK_ROUTE 12 ///< Need to add a route information
#define SOCK_MODE 13 ///< Need to get the mode data of the protocol
#define SOCK_GROUP 14 ///< Need to join a mcast group
///
/// The socket type.
///
typedef enum {
SockDgram, ///< This socket providing datagram service
SockStream ///< This socket providing stream service
} SOCK_TYPE;
///
/// The buffer structure of rcvd data and send data used by socket.
///
typedef struct _SOCK_BUFFER {
UINT32 HighWater; ///< The buffersize upper limit of sock_buffer
UINT32 LowWater; ///< The low water mark of sock_buffer
NET_BUF_QUEUE *DataQueue; ///< The queue to buffer data
} SOCK_BUFFER;
/**
The handler of protocol for request from socket.
@param Socket The socket issuing the request to protocol
@param Request The request issued by socket
@param RequestData The request related data
@retval EFI_SUCCESS The socket request is completed successfully.
@retval other The error status returned by the corresponding TCP
layer function.
**/
typedef
EFI_STATUS
(*SOCK_PROTO_HANDLER) (
IN SOCKET *Socket,
IN UINT8 Request,
IN VOID *RequestData
);
//
// Socket provided oprerations for low layer protocol
//
//
// Socket provided operations for user interface
//
/**
Set the state of the socket.
@param Sock Pointer to the socket.
@param State The new socket state to be set.
**/
VOID
SockSetState (
IN OUT SOCKET *Sock,
IN UINT8 State
);
/**
Called by the low layer protocol to indicate the socket a connection is
established.
This function just changes the socket's state to SO_CONNECTED
and signals the token used for connection establishment.
@param Sock Pointer to the socket associated with the
established connection.
**/
VOID
SockConnEstablished (
IN SOCKET *Sock
);
/**
Called by the low layer protocol to indicate the connection is closed.
This function flushes the socket, sets the state to SO_CLOSED and signals
the close token.
@param Sock Pointer to the socket associated with the closed
connection.
**/
VOID
SockConnClosed (
IN OUT SOCKET *Sock
);
/**
Called by low layer protocol to indicate that some data is sent or processed.
This function trims the sent data in the socket send buffer, signals the data
token if proper.
@param Sock Pointer to the socket.
@param Count The length of the data processed or sent, in bytes.
**/
VOID
SockDataSent (
IN SOCKET *Sock,
IN UINT32 Count
);
/**
Called by the low layer protocol to copy some data in socket send
buffer starting from the specific offset to a buffer provided by
the caller.
@param Sock Pointer to the socket.
@param Offset The start point of the data to be copied.
@param Len The length of the data to be copied.
@param Dest Pointer to the destination to copy the data.
@return The data size copied.
**/
UINT32
SockGetDataToSend (
IN SOCKET *Sock,
IN UINT32 Offset,
IN UINT32 Len,
IN UINT8 *Dest
);
/**
Called by the low layer protocol to indicate that there
will be no more data from the communication peer.
This function set the socket's state to SO_NO_MORE_DATA and
signal all queued IO tokens with the error status EFI_CONNECTION_FIN.
@param Sock Pointer to the socket.
**/
VOID
SockNoMoreData (
IN OUT SOCKET *Sock
);
/**
Called by the low layer protocol to deliver received data to socket layer.
This function will append the data to the socket receive buffer, set ther
urgent data length and then check if any receive token can be signaled.
@param Sock Pointer to the socket.
@param NetBuffer Pointer to the buffer that contains the received
data.
@param UrgLen The length of the urgent data in the received data.
**/
VOID
SockDataRcvd (
IN SOCKET *Sock,
IN OUT NET_BUF *NetBuffer,
IN UINT32 UrgLen
);
/**
Get the length of the free space of the specific socket buffer.
@param Sock Pointer to the socket.
@param Which Flag to indicate which socket buffer to check,
either send buffer or receive buffer.
@return The length of the free space, in bytes.
**/
UINT32
SockGetFreeSpace (
IN SOCKET *Sock,
IN UINT32 Which
);
/**
Clone a new socket including its associated protocol control block.
@param Sock Pointer to the socket to be cloned.
@return Pointer to the newly cloned socket. If NULL, error condition occurred.
**/
SOCKET *
SockClone (
IN SOCKET *Sock
);
///
/// Proto type of the create callback
///
typedef
EFI_STATUS
(*SOCK_CREATE_CALLBACK) (
IN SOCKET *This,
IN VOID *Context
);
///
/// Proto type of the destroy callback
///
typedef
VOID
(*SOCK_DESTROY_CALLBACK) (
IN SOCKET *This,
IN VOID *Context
);
///
/// The initialize data for create a new socket.
///
typedef struct _SOCK_INIT_DATA {
SOCK_TYPE Type;
UINT8 State;
SOCKET *Parent; ///< The parent of this socket
UINT32 BackLog; ///< The connection limit for listening socket
UINT32 SndBufferSize; ///< The high water mark of send buffer
UINT32 RcvBufferSize; ///< The high water mark of receive buffer
VOID *Protocol; ///< The pointer to protocol function template
///< wanted to install on socket
//
// Callbacks after socket is created and before socket is to be destroyed.
//
SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created
SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied
VOID *Context; ///< The context of the callback
//
// Opaque protocol data.
//
VOID *ProtoData;
UINT32 DataSize;
SOCK_PROTO_HANDLER ProtoHandler; ///< The handler of protocol for socket request
EFI_HANDLE DriverBinding; ///< The driver binding handle
} SOCK_INIT_DATA;
///
/// The union type of TCP and UDP protocol.
///
typedef union _NET_PROTOCOL {
EFI_TCP4_PROTOCOL TcpProtocol; ///< Tcp protocol
EFI_UDP4_PROTOCOL UdpProtocol; ///< Udp protocol
} NET_PROTOCOL;
///
/// The socket structure representing a network service access point
///
struct _SOCKET {
//
// Socket description information
//
UINT32 Signature; ///< Signature of the socket
EFI_HANDLE SockHandle; ///< The virtual handle of the socket
EFI_HANDLE DriverBinding; ///< Socket's driver binding protocol
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
LIST_ENTRY Link;
UINT8 ConfigureState;
SOCK_TYPE Type;
UINT8 State;
UINT16 Flag;
EFI_LOCK Lock; ///< The lock of socket
SOCK_BUFFER SndBuffer; ///< Send buffer of application's data
SOCK_BUFFER RcvBuffer; ///< Receive buffer of received data
EFI_STATUS SockError; ///< The error returned by low layer protocol
BOOLEAN InDestroy;
//
// Fields used to manage the connection request
//
UINT32 BackLog; ///< the limit of connection to this socket
UINT32 ConnCnt; ///< the current count of connections to it
SOCKET *Parent; ///< listening parent that accept the connection
LIST_ENTRY ConnectionList; ///< the connections maintained by this socket
//
// The queue to buffer application's asynchronous token
//
LIST_ENTRY ListenTokenList;
LIST_ENTRY RcvTokenList;
LIST_ENTRY SndTokenList;
LIST_ENTRY ProcessingSndTokenList;
SOCK_COMPLETION_TOKEN *ConnectionToken; ///< app's token to signal if connected
SOCK_COMPLETION_TOKEN *CloseToken; ///< app's token to signal if closed
//
// Interface for low level protocol
//
SOCK_PROTO_HANDLER ProtoHandler; ///< The request handler of protocol
UINT8 ProtoReserved[PROTO_RESERVED_LEN]; ///< Data fields reserved for protocol
NET_PROTOCOL NetProtocol; ///< TCP or UDP protocol socket used
//
// Callbacks after socket is created and before socket is to be destroyed.
//
SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created
SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied
VOID *Context; ///< The context of the callback
};
///
/// The token structure buffered in socket layer.
///
typedef struct _SOCK_TOKEN {
LIST_ENTRY TokenList; ///< The entry to add in the token list
SOCK_COMPLETION_TOKEN *Token; ///< The application's token
UINT32 RemainDataLen; ///< Unprocessed data length
SOCKET *Sock; ///< The poninter to the socket this token
///< belongs to
} SOCK_TOKEN;
///
/// Reserved data to access the NET_BUF delivered by UDP driver.
///
typedef struct _UDP_RSV_DATA {
EFI_TIME TimeStamp;
EFI_UDP4_SESSION_DATA Session;
} UDP_RSV_DATA;
///
/// Reserved data to access the NET_BUF delivered by TCP driver.
///
typedef struct _TCP_RSV_DATA {
UINT32 UrgLen;
} TCP_RSV_DATA;
/**
Create a socket and its associated protocol control block
with the intial data SockInitData and protocol specific
data ProtoData.
@param SockInitData Inital data to setting the socket.
@return Pointer to the newly created socket. If NULL, error condition occured.
**/
SOCKET *
SockCreateChild (
IN SOCK_INIT_DATA *SockInitData
);
/**
Destroy the socket Sock and its associated protocol control block.
@param Sock The socket to be destroyed.
@retval EFI_SUCCESS The socket Sock is destroyed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockDestroyChild (
IN SOCKET *Sock
);
/**
Configure the specific socket Sock using configuration data ConfigData.
@param Sock Pointer to the socket to be configured.
@param ConfigData Pointer to the configuration data.
@retval EFI_SUCCESS The socket is configured successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
socket is already configured.
**/
EFI_STATUS
SockConfigure (
IN SOCKET *Sock,
IN VOID *ConfigData
);
/**
Initiate a connection establishment process.
@param Sock Pointer to the socket to initiate the initate the
connection.
@param Token Pointer to the token used for the connection
operation.
@retval EFI_SUCCESS The connection is initialized successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be an active one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockConnect (
IN SOCKET *Sock,
IN VOID *Token
);
/**
Issue a listen token to get an existed connected network instance
or wait for a connection if there is none.
@param Sock Pointer to the socket to accept connections.
@param Token The token to accept a connection.
@retval EFI_SUCCESS Either a connection is accpeted or the Token is
buffered for further acception.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be a passive one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
**/
EFI_STATUS
SockAccept (
IN SOCKET *Sock,
IN VOID *Token
);
/**
Issue a token with data to the socket to send out.
@param Sock Pointer to the socket to process the token with
data.
@param Token The token with data that needs to send out.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockSend (
IN SOCKET *Sock,
IN VOID *Token
);
/**
Issue a token to get data from the socket.
@param Sock Pointer to the socket to get data from.
@param Token The token to store the received data from the
socket.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockRcv (
IN SOCKET *Sock,
IN VOID *Token
);
/**
Reset the socket and its associated protocol control block.
@param Sock Pointer to the socket to be flushed.
@retval EFI_SUCCESS The socket is flushed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockFlush (
IN SOCKET *Sock
);
/**
Close or abort the socket associated connection.
@param Sock Pointer to the socket of the connection to close or
abort.
@param Token The token for close operation.
@param OnAbort TRUE for aborting the connection, FALSE to close it.
@retval EFI_SUCCESS The close or abort operation is initialized
successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockClose (
IN SOCKET *Sock,
IN VOID *Token,
IN BOOLEAN OnAbort
);
/**
Get the mode data of the low layer protocol.
@param Sock Pointer to the socket to get mode data from.
@param Mode Pointer to the data to store the low layer mode
information.
@retval EFI_SUCCESS The mode data is got successfully.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockGetMode (
IN SOCKET *Sock,
IN OUT VOID *Mode
);
/**
Add or remove route information in IP route table associated
with this socket.
@param Sock Pointer to the socket associated with the IP route
table to operate on.
@param RouteInfo Pointer to the route information to be processed.
@retval EFI_SUCCESS The route table is updated successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockRoute (
IN SOCKET *Sock,
IN VOID *RouteInfo
);
//
// Supporting function to operate on socket buffer
//
/**
Get the first buffer block in the specific socket buffer.
@param Sockbuf Pointer to the socket buffer.
@return Pointer to the first buffer in the queue. NULL if the queue is empty.
**/
NET_BUF *
SockBufFirst (
IN SOCK_BUFFER *Sockbuf
);
/**
Get the next buffer block in the specific socket buffer.
@param Sockbuf Pointer to the socket buffer.
@param SockEntry Pointer to the buffer block prior to the required
one.
@return Pointer to the buffer block next to SockEntry. NULL if SockEntry is
the tail or head entry.
**/
NET_BUF *
SockBufNext (
IN SOCK_BUFFER *Sockbuf,
IN NET_BUF *SockEntry
);
#endif

View File

@ -1,717 +0,0 @@
/** @file
Tcp request dispatcher implementation.
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
#define TCP_COMP_VAL(Min, Max, Default, Val) \
((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
/**
Add or remove a route entry in the IP route table associated with this TCP instance.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param RouteInfo Pointer to the route info to be processed.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The driver instance has not been started.
@retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table
(when RouteInfo->DeleteRoute is TRUE).
@retval EFI_ACCESS_DENIED The route is already defined in the routing table
(when RouteInfo->DeleteRoute is FALSE).
**/
EFI_STATUS
Tcp4Route (
IN TCP_CB *Tcb,
IN TCP4_ROUTE_INFO *RouteInfo
)
{
EFI_IP4_PROTOCOL *Ip4;
Ip4 = Tcb->IpInfo->Ip.Ip4;
ASSERT (Ip4 != NULL);
return Ip4->Routes (
Ip4,
RouteInfo->DeleteRoute,
RouteInfo->SubnetAddress,
RouteInfo->SubnetMask,
RouteInfo->GatewayAddress
);
}
/**
Get the operational settings of this TCP instance.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Mode Pointer to the buffer to store the operational
settings.
@retval EFI_SUCCESS The mode data is read.
@retval EFI_NOT_STARTED No configuration data is available because this
instance hasn't been started.
**/
EFI_STATUS
Tcp4GetMode (
IN TCP_CB *Tcb,
IN OUT TCP4_MODE_DATA *Mode
)
{
SOCKET *Sock;
EFI_TCP4_CONFIG_DATA *ConfigData;
EFI_TCP4_ACCESS_POINT *AccessPoint;
EFI_TCP4_OPTION *Option;
EFI_IP4_PROTOCOL *Ip;
Sock = Tcb->Sk;
if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
return EFI_NOT_STARTED;
}
if (Mode->Tcp4State != NULL) {
*(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;
}
if (Mode->Tcp4ConfigData != NULL) {
ConfigData = Mode->Tcp4ConfigData;
AccessPoint = &(ConfigData->AccessPoint);
Option = ConfigData->ControlOption;
ConfigData->TypeOfService = Tcb->Tos;
ConfigData->TimeToLive = Tcb->Ttl;
AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask);
AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
if (Option != NULL) {
Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
Option->DataRetries = Tcb->MaxRexmit;
Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
Option->KeepAliveProbes = Tcb->MaxKeepAlive;
Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
Option->EnableSelectiveAck = FALSE;
Option->EnablePathMtuDiscovery = FALSE;
}
}
Ip = Tcb->IpInfo->Ip.Ip4;
ASSERT (Ip != NULL);
return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
}
/**
If AP->StationPort isn't zero, check whether the access point
is registered, else generate a random station port for this
access point.
@param AP Pointer to the access point.
@retval EFI_SUCCESS The check is passed or the port is assigned.
@retval EFI_INVALID_PARAMETER The non-zero station port is already used.
@retval EFI_OUT_OF_RESOURCES No port can be allocated.
**/
EFI_STATUS
Tcp4Bind (
IN EFI_TCP4_ACCESS_POINT *AP
)
{
BOOLEAN Cycle;
if (0 != AP->StationPort) {
//
// check if a same endpoint is bound
//
if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// generate a random port
//
Cycle = FALSE;
if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
mTcp4RandomPort = TCP4_PORT_KNOWN;
}
mTcp4RandomPort++;
while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
mTcp4RandomPort++;
if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
if (Cycle) {
DEBUG ((EFI_D_ERROR, "Tcp4Bind: no port can be allocated "
"for this pcb\n"));
return EFI_OUT_OF_RESOURCES;
}
mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
Cycle = TRUE;
}
}
AP->StationPort = mTcp4RandomPort;
}
return EFI_SUCCESS;
}
/**
Flush the Tcb add its associated protocols.
@param Tcb Pointer to the TCP_CB to be flushed.
**/
VOID
Tcp4FlushPcb (
IN TCP_CB *Tcb
)
{
SOCKET *Sock;
IpIoConfigIp (Tcb->IpInfo, NULL);
Sock = Tcb->Sk;
if (SOCK_IS_CONFIGURED (Sock)) {
RemoveEntryList (&Tcb->List);
//
// Uninstall the device path protocol.
//
if (Sock->DevicePath != NULL) {
gBS->UninstallProtocolInterface (
Sock->SockHandle,
&gEfiDevicePathProtocolGuid,
Sock->DevicePath
);
FreePool (Sock->DevicePath);
}
}
NetbufFreeList (&Tcb->SndQue);
NetbufFreeList (&Tcb->RcvQue);
Tcb->State = TCP_CLOSED;
}
/**
Attach a Pcb to the socket.
@param Sk Pointer to the socket of this TCP instance.
@retval EFI_SUCCESS The operation is completed successfully.
@retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
**/
EFI_STATUS
Tcp4AttachPcb (
IN SOCKET *Sk
)
{
TCP_CB *Tcb;
TCP4_PROTO_DATA *ProtoData;
IP_IO *IpIo;
EFI_STATUS Status;
VOID *Ip;
Tcb = AllocateZeroPool (sizeof (TCP_CB));
if (Tcb == NULL) {
DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));
return EFI_OUT_OF_RESOURCES;
}
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
IpIo = ProtoData->TcpService->IpIo;
//
// Create an IpInfo for this Tcb.
//
Tcb->IpInfo = IpIoAddIp (IpIo);
if (Tcb->IpInfo == NULL) {
FreePool (Tcb);
return EFI_OUT_OF_RESOURCES;
}
//
// Open the new created IP instance BY_CHILD.
//
Status = gBS->OpenProtocol (
Tcb->IpInfo->ChildHandle,
&gEfiIp4ProtocolGuid,
&Ip,
IpIo->Image,
Sk->SockHandle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
IpIoRemoveIp (IpIo, Tcb->IpInfo);
return Status;
}
InitializeListHead (&Tcb->List);
InitializeListHead (&Tcb->SndQue);
InitializeListHead (&Tcb->RcvQue);
Tcb->State = TCP_CLOSED;
Tcb->Sk = Sk;
ProtoData->TcpPcb = Tcb;
return EFI_SUCCESS;
}
/**
Detach the Pcb of the socket.
@param Sk Pointer to the socket of this TCP instance.
**/
VOID
Tcp4DetachPcb (
IN SOCKET *Sk
)
{
TCP4_PROTO_DATA *ProtoData;
TCP_CB *Tcb;
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
Tcb = ProtoData->TcpPcb;
ASSERT (Tcb != NULL);
Tcp4FlushPcb (Tcb);
IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
FreePool (Tcb);
ProtoData->TcpPcb = NULL;
}
/**
Configure the Pcb using CfgData.
@param Sk Pointer to the socket of this TCP instance.
@param CfgData Pointer to the TCP configuration data.
@retval EFI_SUCCESS The operation is completed successfully.
@retval EFI_INVALID_PARAMETER A same access point has been configured in
another TCP instance.
@retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
**/
EFI_STATUS
Tcp4ConfigurePcb (
IN SOCKET *Sk,
IN EFI_TCP4_CONFIG_DATA *CfgData
)
{
EFI_IP4_CONFIG_DATA IpCfgData;
EFI_STATUS Status;
EFI_TCP4_OPTION *Option;
TCP4_PROTO_DATA *TcpProto;
TCP_CB *Tcb;
ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
Tcb = TcpProto->TcpPcb;
ASSERT (Tcb != NULL);
//
// Add Ip for send pkt to the peer
//
CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData));
IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
IpCfgData.ReceiveTimeout = (UINT32) (-1);
//
// Configure the IP instance this Tcb consumes.
//
Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
if (EFI_ERROR (Status)) {
goto OnExit;
}
//
// Get the default address info if the instance is configured to use default address.
//
if (CfgData->AccessPoint.UseDefaultAddress) {
CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
}
//
// check if we can bind this endpoint in CfgData
//
Status = Tcp4Bind (&(CfgData->AccessPoint));
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed "
"with %r\n", Status));
goto OnExit;
}
//
// Initalize the operating information in this Tcb
//
ASSERT (Tcb->State == TCP_CLOSED &&
IsListEmpty (&Tcb->SndQue) &&
IsListEmpty (&Tcb->RcvQue));
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
Tcb->State = TCP_CLOSED;
Tcb->SndMss = 536;
Tcb->RcvMss = TcpGetRcvMss (Sk);
Tcb->SRtt = 0;
Tcb->Rto = 3 * TCP_TICK_HZ;
Tcb->CWnd = Tcb->SndMss;
Tcb->Ssthresh = 0xffffffff;
Tcb->CongestState = TCP_CONGEST_OPEN;
Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
Tcb->MaxRexmit = TCP_MAX_LOSS;
Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
Tcb->ConnectTimeout = TCP_CONNECT_TIME;
//
// initialize Tcb in the light of CfgData
//
Tcb->Ttl = CfgData->TimeToLive;
Tcb->Tos = CfgData->TypeOfService;
Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;
CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->AccessPoint.SubnetMask);
if (CfgData->AccessPoint.ActiveFlag) {
CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
} else {
Tcb->RemoteEnd.Ip = 0;
Tcb->RemoteEnd.Port = 0;
}
Option = CfgData->ControlOption;
if (Option != NULL) {
SET_RCV_BUFFSIZE (
Sk,
(UINT32) (TCP_COMP_VAL (
TCP_RCV_BUF_SIZE_MIN,
TCP_RCV_BUF_SIZE,
TCP_RCV_BUF_SIZE,
Option->ReceiveBufferSize
)
)
);
SET_SND_BUFFSIZE (
Sk,
(UINT32) (TCP_COMP_VAL (
TCP_SND_BUF_SIZE_MIN,
TCP_SND_BUF_SIZE,
TCP_SND_BUF_SIZE,
Option->SendBufferSize
)
)
);
SET_BACKLOG (
Sk,
(UINT32) (TCP_COMP_VAL (
TCP_BACKLOG_MIN,
TCP_BACKLOG,
TCP_BACKLOG,
Option->MaxSynBackLog
)
)
);
Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
TCP_MAX_LOSS_MIN,
TCP_MAX_LOSS,
TCP_MAX_LOSS,
Option->DataRetries
);
Tcb->FinWait2Timeout = TCP_COMP_VAL (
TCP_FIN_WAIT2_TIME,
TCP_FIN_WAIT2_TIME_MAX,
TCP_FIN_WAIT2_TIME,
(UINT32) (Option->FinTimeout * TCP_TICK_HZ)
);
if (Option->TimeWaitTimeout != 0) {
Tcb->TimeWaitTimeout = TCP_COMP_VAL (
TCP_TIME_WAIT_TIME,
TCP_TIME_WAIT_TIME_MAX,
TCP_TIME_WAIT_TIME,
(UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)
);
} else {
Tcb->TimeWaitTimeout = 0;
}
if (Option->KeepAliveProbes != 0) {
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
TCP_MAX_KEEPALIVE_MIN,
TCP_MAX_KEEPALIVE,
TCP_MAX_KEEPALIVE,
Option->KeepAliveProbes
);
Tcb->KeepAliveIdle = TCP_COMP_VAL (
TCP_KEEPALIVE_IDLE_MIN,
TCP_KEEPALIVE_IDLE_MAX,
TCP_KEEPALIVE_IDLE_MIN,
(UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
);
Tcb->KeepAlivePeriod = TCP_COMP_VAL (
TCP_KEEPALIVE_PERIOD_MIN,
TCP_KEEPALIVE_PERIOD,
TCP_KEEPALIVE_PERIOD,
(UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
);
}
Tcb->ConnectTimeout = TCP_COMP_VAL (
TCP_CONNECT_TIME_MIN,
TCP_CONNECT_TIME,
TCP_CONNECT_TIME,
(UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
);
if (!Option->EnableNagle) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
}
if (!Option->EnableTimeStamp) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
}
if (!Option->EnableWindowScaling) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
}
}
//
// The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
// determined, construct the IP device path and install it.
//
Status = TcpInstallDevicePath (Sk);
if (EFI_ERROR (Status)) {
goto OnExit;
}
//
// update state of Tcb and socket
//
if (!CfgData->AccessPoint.ActiveFlag) {
TcpSetState (Tcb, TCP_LISTEN);
SockSetState (Sk, SO_LISTENING);
Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
} else {
Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
}
TcpInsertTcb (Tcb);
OnExit:
return Status;
}
/**
The procotol handler provided to the socket layer, used to
dispatch the socket level requests by calling the corresponding
TCP layer functions.
@param Sock Pointer to the socket of this TCP instance.
@param Request The code of this operation request.
@param Data Pointer to the operation specific data passed in
together with the operation request.
@retval EFI_SUCCESS The socket request is completed successfully.
@retval other The error status returned by the corresponding TCP
layer function.
**/
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN UINT8 Request,
IN VOID *Data OPTIONAL
)
{
TCP_CB *Tcb;
TCP4_PROTO_DATA *ProtoData;
EFI_IP4_PROTOCOL *Ip;
ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
Tcb = ProtoData->TcpPcb;
switch (Request) {
case SOCK_POLL:
Ip = ProtoData->TcpService->IpIo->Ip.Ip4;
Ip->Poll (Ip);
break;
case SOCK_CONSUMED:
//
// After user received data from socket buffer, socket will
// notify TCP using this message to give it a chance to send out
// window update information
//
ASSERT (Tcb != NULL);
TcpOnAppConsume (Tcb);
break;
case SOCK_SND:
ASSERT (Tcb != NULL);
TcpOnAppSend (Tcb);
break;
case SOCK_CLOSE:
TcpOnAppClose (Tcb);
break;
case SOCK_ABORT:
TcpOnAppAbort (Tcb);
break;
case SOCK_SNDPUSH:
Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
break;
case SOCK_SNDURG:
Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
break;
case SOCK_CONNECT:
TcpOnAppConnect (Tcb);
break;
case SOCK_ATTACH:
return Tcp4AttachPcb (Sock);
case SOCK_FLUSH:
Tcp4FlushPcb (Tcb);
break;
case SOCK_DETACH:
Tcp4DetachPcb (Sock);
break;
case SOCK_CONFIGURE:
return Tcp4ConfigurePcb (
Sock,
(EFI_TCP4_CONFIG_DATA *) Data
);
case SOCK_MODE:
ASSERT ((Data != NULL) && (Tcb != NULL));
return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
case SOCK_ROUTE:
ASSERT ((Data != NULL) && (Tcb != NULL));
return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
default:
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}

View File

@ -1,782 +0,0 @@
/** @file
Tcp driver function.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
UINT16 mTcp4RandomPort;
extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2;
extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
TCP4_HEARTBEAT_TIMER mTcp4Timer = {
NULL,
0
};
EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {
Tcp4GetModeData,
Tcp4Configure,
Tcp4Routes,
Tcp4Connect,
Tcp4Accept,
Tcp4Transmit,
Tcp4Receive,
Tcp4Close,
Tcp4Cancel,
Tcp4Poll
};
SOCK_INIT_DATA mTcp4DefaultSockData = {
SockStream,
0,
NULL,
TCP_BACKLOG,
TCP_SND_BUF_SIZE,
TCP_RCV_BUF_SIZE,
&mTcp4ProtocolTemplate,
Tcp4CreateSocketCallback,
Tcp4DestroySocketCallback,
NULL,
NULL,
0,
Tcp4Dispatcher,
NULL,
};
EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {
Tcp4DriverBindingSupported,
Tcp4DriverBindingStart,
Tcp4DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {
Tcp4ServiceBindingCreateChild,
Tcp4ServiceBindingDestroyChild
};
/**
Create and start the heartbeat timer for TCP driver.
@retval EFI_SUCCESS The timer is successfully created and started.
@retval other The timer is not created.
**/
EFI_STATUS
Tcp4CreateTimer (
VOID
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (mTcp4Timer.RefCnt == 0) {
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
TcpTicking,
NULL,
&mTcp4Timer.TimerEvent
);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer (
mTcp4Timer.TimerEvent,
TimerPeriodic,
(UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
);
}
}
if (!EFI_ERROR (Status)) {
mTcp4Timer.RefCnt++;
}
return Status;
}
/**
Stop and destroy the heartbeat timer for TCP driver.
**/
VOID
Tcp4DestroyTimer (
VOID
)
{
ASSERT (mTcp4Timer.RefCnt > 0);
mTcp4Timer.RefCnt--;
if (mTcp4Timer.RefCnt > 0) {
return;
}
gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
gBS->CloseEvent (mTcp4Timer.TimerEvent);
mTcp4Timer.TimerEvent = NULL;
}
/**
Callback function which provided by user to remove one node in NetDestroyLinkList process.
@param[in] Entry The entry to be removed.
@param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
@retval EFI_SUCCESS The entry has been removed successfully.
@retval Others Fail to remove the entry.
**/
EFI_STATUS
EFIAPI
Tcp4DestroyChildEntryInHandleBuffer (
IN LIST_ENTRY *Entry,
IN VOID *Context
)
{
SOCKET *Sock;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
UINTN NumberOfChildren;
EFI_HANDLE *ChildHandleBuffer;
if (Entry == NULL || Context == NULL) {
return EFI_INVALID_PARAMETER;
}
Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);
ServiceBinding = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
NumberOfChildren = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
ChildHandleBuffer = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {
return EFI_SUCCESS;
}
return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
}
/**
The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.
@param ImageHandle The firmware allocated handle for this
driver image.
@param SystemTable Pointer to the EFI system table.
@retval EFI_SUCCESS Driver loaded.
@retval other Driver not loaded.
**/
EFI_STATUS
EFIAPI
Tcp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINT32 Seed;
//
// Install the TCP4 Driver Binding Protocol
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&mTcp4DriverBinding,
ImageHandle,
&gTcp4ComponentName,
&gTcp4ComponentName2
);
ASSERT_EFI_ERROR (Status);
//
// Initialize ISS and random port.
//
Seed = NetRandomInitSeed ();
mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN +
(UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));
return Status;
}
/**
Tests to see if this driver supports a given controller.
If a child device is provided, it further tests to see if this driver supports
creating a handle for the specified child device.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle The handle of the controller to test. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param RemainingDevicePath A pointer to the remaining portion of a device path.
This parameter is ignored by device drivers, and is optional for bus drivers.
@retval EFI_SUCCESS The device specified by ControllerHandle and
RemainingDevicePath is supported by the driver
specified by This.
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by
the driver specified by This.
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by a
different driver or an application that requires
exclusive access.
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
RemainingDevicePath is not supported by the driver
specified by This.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
//
// Test for the Tcp4ServiceBinding Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Test for the Ip4 Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
return Status;
}
/**
Start this driver on ControllerHandle.
The Start() function is designed to be invoked from the EFI boot service
ConnectController(). As a result, much of the error checking on the parameters
to Start() has been moved into this common boot service. It is legal to call
Start() from other locations, but the following calling restrictions must be
followed or the system behavior will not be deterministic.
1. ControllerHandle must be a valid EFI_HANDLE.
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
aligned EFI_DEVICE_PATH_PROTOCOL.
3. Prior to calling Start(), the Supported() function for the driver specified
by This must have been called with the same calling parameters, and Supported()
must have returned EFI_SUCCESS.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle The handle of the controller to start. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param RemainingDevicePath A pointer to the remaining portion of a device path.
This parameter is ignored by device drivers, and is
optional for bus drivers.
@retval EFI_SUCCESS The device was started.
@retval EFI_ALREADY_STARTED The device could not be started due to a device error.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
of resources.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
TCP4_SERVICE_DATA *TcpServiceData;
IP_IO_OPEN_DATA OpenData;
TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
if (NULL == TcpServiceData) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
" resource to create a Tcp Servcie Data\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Create a new IP IO to Consume it
//
TcpServiceData->IpIo = IpIoCreate (
This->DriverBindingHandle,
ControllerHandle,
IP_VERSION_4
);
if (NULL == TcpServiceData->IpIo) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"
" resource to create an Ip Io\n"));
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
}
//
// Configure and start IpIo.
//
ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
CopyMem (
&OpenData.IpConfigData.Ip4CfgData,
&mIp4IoDefaultIpConfigData,
sizeof (EFI_IP4_CONFIG_DATA)
);
OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
OpenData.PktRcvdNotify = Tcp4RxCallback;
Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create the timer event used by TCP driver
//
Status = Tcp4CreateTimer ();
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"
" Event failed with %r\n", Status));
goto ON_ERROR;
}
//
// Install the Tcp4ServiceBinding Protocol on the
// controller handle
//
TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
&TcpServiceData->Tcp4ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
" Protocol failed for %r\n", Status));
Tcp4DestroyTimer ();
goto ON_ERROR;
}
//
// Initialize member in TcpServiceData
//
TcpServiceData->ControllerHandle = ControllerHandle;
TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
InitializeListHead (&TcpServiceData->SocketList);
return EFI_SUCCESS;
ON_ERROR:
if (TcpServiceData->IpIo != NULL) {
IpIoDestroy (TcpServiceData->IpIo);
TcpServiceData->IpIo = NULL;
}
FreePool (TcpServiceData);
return Status;
}
/**
Stop this driver on ControllerHandle.
The Stop() function is designed to be invoked from the EFI boot service
DisconnectController(). As a result, much of the error checking on the parameters
to Stop() has been moved into this common boot service. It is legal to call Stop()
from other locations, but the following calling restrictions must be followed
or the system behavior will not be deterministic.
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
to this same driver's Start() function.
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
EFI_HANDLE. In addition, all of these handles must have been created in this
driver's Start() function, and the Start() function must have called OpenProtocol()
on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle A handle to the device being stopped. The handle must
support a bus specific I/O protocol for the driver
to use to stop the device.
@param NumberOfChildren The number of child device handles in ChildHandleBuffer.
@param ChildHandleBuffer An array of child handles to be freed. May be NULL if
NumberOfChildren is 0.
@retval EFI_SUCCESS The device was stopped.
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EFI_HANDLE NicHandle;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
TCP4_SERVICE_DATA *TcpServiceData;
LIST_ENTRY *List;
TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
// Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
//
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
if (NicHandle == NULL) {
return EFI_SUCCESS;
}
//
// Retrieve the TCP driver Data Structure
//
Status = gBS->OpenProtocol (
NicHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "
" Binding Protocol failed with %r\n", Status));
return EFI_DEVICE_ERROR;
}
TcpServiceData = TCP4_FROM_THIS (ServiceBinding);
if (NumberOfChildren != 0) {
List = &TcpServiceData->SocketList;
Context.ServiceBinding = ServiceBinding;
Context.NumberOfChildren = NumberOfChildren;
Context.ChildHandleBuffer = ChildHandleBuffer;
Status = NetDestroyLinkList (
List,
Tcp4DestroyChildEntryInHandleBuffer,
&Context,
NULL
);
} else if (IsListEmpty (&TcpServiceData->SocketList)) {
//
// Uninstall TCP servicebinding protocol
//
gBS->UninstallMultipleProtocolInterfaces (
NicHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
ServiceBinding,
NULL
);
//
// Destroy the IpIO consumed by TCP driver
//
IpIoDestroy (TcpServiceData->IpIo);
TcpServiceData->IpIo = NULL;
//
// Destroy the heartbeat timer.
//
Tcp4DestroyTimer ();
if (gTcpControllerNameTable != NULL) {
FreeUnicodeStringTable (gTcpControllerNameTable);
gTcpControllerNameTable = NULL;
}
//
// Release the TCP service data
//
FreePool (TcpServiceData);
Status = EFI_SUCCESS;
}
return Status;
}
/**
Open Ip4 and device path protocols for a created socket, and insert it in
socket list.
@param This Pointer to the socket just created
@param Context Context of the socket
@retval EFI_SUCCESS This protocol is installed successfully.
@retval other Some error occured.
**/
EFI_STATUS
Tcp4CreateSocketCallback (
IN SOCKET *This,
IN VOID *Context
)
{
EFI_STATUS Status;
TCP4_SERVICE_DATA *TcpServiceData;
EFI_IP4_PROTOCOL *Ip4;
TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
//
// Open the default Ip4 protocol of IP_IO BY_DRIVER.
//
Status = gBS->OpenProtocol (
TcpServiceData->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
(VOID **) &Ip4,
TcpServiceData->DriverBindingHandle,
This->SockHandle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Open the device path on the handle where service binding resides on.
//
Status = gBS->OpenProtocol (
TcpServiceData->ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **) &This->ParentDevicePath,
TcpServiceData->DriverBindingHandle,
This->SockHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
TcpServiceData->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
TcpServiceData->DriverBindingHandle,
This->SockHandle
);
} else {
//
// Insert this socket into the SocketList.
//
InsertTailList (&TcpServiceData->SocketList, &This->Link);
}
return Status;
}
/**
Close Ip4 and device path protocols for a socket, and remove it from socket list.
@param This Pointer to the socket to be removed
@param Context Context of the socket
**/
VOID
Tcp4DestroySocketCallback (
IN SOCKET *This,
IN VOID *Context
)
{
TCP4_SERVICE_DATA *TcpServiceData;
TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
//
// Remove this node from the list.
//
RemoveEntryList (&This->Link);
//
// Close the Ip4 protocol.
//
gBS->CloseProtocol (
TcpServiceData->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
TcpServiceData->DriverBindingHandle,
This->SockHandle
);
}
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
ChildHandle.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
a new handle is created. If it is a pointer to an existing UEFI
handle, then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
)
{
SOCKET *Sock;
TCP4_SERVICE_DATA *TcpServiceData;
TCP4_PROTO_DATA TcpProto;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (NULL == This || NULL == ChildHandle) {
return EFI_INVALID_PARAMETER;
}
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Status = EFI_SUCCESS;
TcpServiceData = TCP4_FROM_THIS (This);
TcpProto.TcpService = TcpServiceData;
TcpProto.TcpPcb = NULL;
//
// Create a tcp instance with defualt Tcp default
// sock init data and TcpProto
//
mTcp4DefaultSockData.ProtoData = &TcpProto;
mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);
mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
Sock = SockCreateChild (&mTcp4DefaultSockData);
if (NULL == Sock) {
DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "
"No resource to create a Tcp Child\n"));
Status = EFI_OUT_OF_RESOURCES;
} else {
*ChildHandle = Sock->SockHandle;
}
mTcp4DefaultSockData.ProtoData = NULL;
gBS->RestoreTPL (OldTpl);
return Status;
}
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Handle of the child to destroy
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
being removed.
@retval EFI_INVALID_PARAMETER Child handle is NULL.
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
because its services are being used.
@retval other The child handle was not destroyed.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
EFI_TCP4_PROTOCOL *Tcp4;
SOCKET *Sock;
if (NULL == This || NULL == ChildHandle) {
return EFI_INVALID_PARAMETER;
}
//
// retrieve the Tcp4 protocol from ChildHandle
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiTcp4ProtocolGuid,
(VOID **) &Tcp4,
mTcp4DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
} else {
//
// destroy this sock and related Tcp protocol control
// block
//
Sock = SOCK_FROM_THIS (Tcp4);
SockDestroyChild (Sock);
}
return Status;
}

View File

@ -1,342 +0,0 @@
/** @file
Tcp driver function header.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TCP4_DRIVER_H_
#define _TCP4_DRIVER_H_
#include <Protocol/ServiceBinding.h>
#include <Library/IpIoLib.h>
#define TCP4_DRIVER_SIGNATURE SIGNATURE_32 ('T', 'C', 'P', '4')
#define TCP4_PORT_KNOWN 1024
#define TCP4_PORT_USER_RESERVED 65535
#define TCP4_FROM_THIS(a) \
CR ( \
(a), \
TCP4_SERVICE_DATA, \
Tcp4ServiceBinding, \
TCP4_DRIVER_SIGNATURE \
)
///
/// TCP heartbeat tick timer.
///
typedef struct _TCP4_HEARTBEAT_TIMER {
EFI_EVENT TimerEvent; ///< The event assoiated with the timer
INTN RefCnt; ///< Number of reference
} TCP4_HEARTBEAT_TIMER;
///
/// TCP service data
///
typedef struct _TCP4_SERVICE_DATA {
UINT32 Signature;
EFI_HANDLE ControllerHandle;
IP_IO *IpIo; // IP Io consumed by TCP4
EFI_SERVICE_BINDING_PROTOCOL Tcp4ServiceBinding;
EFI_HANDLE DriverBindingHandle;
LIST_ENTRY SocketList;
} TCP4_SERVICE_DATA;
///
/// TCP protocol data
///
typedef struct _TCP4_PROTO_DATA {
TCP4_SERVICE_DATA *TcpService;
TCP_CB *TcpPcb;
} TCP4_PROTO_DATA;
/**
Packet receive callback function provided to IP_IO, used to call
the proper function to handle the packet received by IP.
@param Status Status of the received packet.
@param IcmpErr ICMP error number.
@param NetSession Pointer to the net session of this packet.
@param Pkt Pointer to the recieved packet.
@param Context Pointer to the context configured in IpIoOpen(), not used
now.
@return None
**/
VOID
EFIAPI
Tcp4RxCallback (
IN EFI_STATUS Status,
IN UINT8 IcmpErr,
IN EFI_NET_SESSION_DATA *NetSession,
IN NET_BUF *Pkt,
IN VOID *Context OPTIONAL
);
/**
Send the segment to IP via IpIo function.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the TCP segment to be sent.
@param Src Source address of the TCP segment.
@param Dest Destination address of the TCP segment.
@retval 0 The segment was sent out successfully.
@retval -1 The segment was failed to send.
**/
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dest
);
/**
The procotol handler provided to the socket layer, used to
dispatch the socket level requests by calling the corresponding
TCP layer functions.
@param Sock Pointer to the socket of this TCP instance.
@param Request The code of this operation request.
@param Data Pointer to the operation specific data passed in
together with the operation request.
@retval EFI_SUCCESS The socket request is completed successfully.
@retval other The error status returned by the corresponding TCP
layer function.
**/
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN UINT8 Request,
IN VOID *Data OPTIONAL
);
/**
The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.
@param ImageHandle The firmware allocated handle for this
driver image.
@param SystemTable Pointer to the EFI system table.
@retval EFI_SUCCESS Driver loaded.
@retval other Driver not loaded.
**/
EFI_STATUS
EFIAPI
Tcp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
/**
Tests to see if this driver supports a given controller.
If a child device is provided, it further tests to see if this driver supports
creating a handle for the specified child device.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle The handle of the controller to test. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param RemainingDevicePath A pointer to the remaining portion of a device path.
This parameter is ignored by device drivers, and is optional for bus drivers.
@retval EFI_SUCCESS The device specified by ControllerHandle and
RemainingDevicePath is supported by the driver
specified by This.
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by
the driver specified by This.
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
RemainingDevicePath is already being managed by a
different driver or an application that requires
exclusive access.
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
RemainingDevicePath is not supported by the driver
specified by This.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Start this driver on ControllerHandle.
The Start() function is designed to be invoked from the EFI boot service
ConnectController(). As a result, much of the error checking on the parameters
to Start() has been moved into this common boot service. It is legal to call
Start() from other locations, but the following calling restrictions must be
followed or the system behavior will not be deterministic.
1. ControllerHandle must be a valid EFI_HANDLE.
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
aligned EFI_DEVICE_PATH_PROTOCOL.
3. Prior to calling Start(), the Supported() function for the driver specified
by This must have been called with the same calling parameters, and Supported()
must have returned EFI_SUCCESS.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle The handle of the controller to start. This handle
must support a protocol interface that supplies
an I/O abstraction to the driver.
@param RemainingDevicePath A pointer to the remaining portion of a device path.
This parameter is ignored by device drivers, and is
optional for bus drivers.
@retval EFI_SUCCESS The device was started.
@retval EFI_ALREADY_STARTED The device could not be started due to a device error.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
of resources.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
/**
Stop this driver on ControllerHandle.
The Stop() function is designed to be invoked from the EFI boot service
DisconnectController(). As a result, much of the error checking on the parameters
to Stop() has been moved into this common boot service. It is legal to call Stop()
from other locations, but the following calling restrictions must be followed
or the system behavior will not be deterministic.
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
to this same driver's Start() function.
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
EFI_HANDLE. In addition, all of these handles must have been created in this
driver's Start() function, and the Start() function must have called OpenProtocol()
on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
@param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param ControllerHandle A handle to the device being stopped. The handle must
support a bus specific I/O protocol for the driver
to use to stop the device.
@param NumberOfChildren The number of child device handles in ChildHandleBuffer.
@param ChildHandleBuffer An array of child handles to be freed. May be NULL if
NumberOfChildren is 0.
@retval EFI_SUCCESS The device was stopped.
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
/**
Open Ip4 and device path protocols for a created socket, and insert it in
socket list.
@param This Pointer to the socket just created
@param Context Context of the socket
@retval EFI_SUCCESS This protocol is installed successfully.
@retval other Some error occured.
**/
EFI_STATUS
Tcp4CreateSocketCallback (
IN SOCKET *This,
IN VOID *Context
);
/**
Close Ip4 and device path protocols for a socket, and remove it from socket list.
@param This Pointer to the socket to be removed
@param Context Context of the socket
**/
VOID
Tcp4DestroySocketCallback (
IN SOCKET *This,
IN VOID *Context
);
/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
is a pointer to NULL, then a new handle is created and returned in ChildHandle.
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
ChildHandle.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
a new handle is created. If it is a pointer to an existing UEFI
handle, then the protocol is added to the existing UEFI handle.
@retval EFI_SUCCES The protocol was added to ChildHandle.
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN OUT EFI_HANDLE *ChildHandle
);
/**
Destroys a child handle with a protocol installed on it.
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
last protocol on ChildHandle, then ChildHandle is destroyed.
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
@param ChildHandle Handle of the child to destroy
@retval EFI_SUCCES The protocol was removed from ChildHandle.
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
being removed.
@retval EFI_INVALID_PARAMETER Child handle is NULL.
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
because its services are being used.
@retval other The child handle was not destroyed.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@ -1,94 +0,0 @@
## @file
# This module produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol.
#
# This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol
# upon EFI IPv4 Protocol, to provide basic TCPv4 I/O services. This driver only
# supports IPv4 network stack.
#
# Notes:
# 1) This driver can't co-work with the TcpDxe driver in NetworkPkg.
# 2) This driver might have some issues that have been fixed in the TcpDxe driver
# in NetworkPkg.
# 3) This driver supports fewer features than the TcpDxe driver in NetworkPkg (e.g. IPv6,
# TCP Cancel function).
# 4) TcpDxe driver in NetworkPkg is recommended for use instead of this one even though
# both of them can be used.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Tcp4Dxe
MODULE_UNI_FILE = Tcp4Dxe.uni
FILE_GUID = 6d6963ab-906d-4a65-a7ca-bd40e5d6af4d
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = Tcp4DriverEntryPoint
UNLOAD_IMAGE = NetLibDefaultUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
# DRIVER_BINDING = mTcp4DriverBinding
# COMPONENT_NAME = gTcp4ComponentName
# COMPONENT_NAME2 = gTcp4ComponentName2
#
[Sources]
SockImpl.c
SockInterface.c
Tcp4Proto.h
Tcp4Main.h
SockImpl.h
Tcp4Output.c
Tcp4Timer.c
Tcp4Option.h
Tcp4Dispatcher.c
Tcp4Input.c
Tcp4Misc.c
Tcp4Main.c
Socket.h
ComponentName.c
Tcp4Driver.h
Tcp4Io.c
Tcp4Driver.c
Tcp4Func.h
Tcp4Option.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeServicesTableLib
BaseMemoryLib
MemoryAllocationLib
DebugLib
NetLib
IpIoLib
DevicePathLib
DpcLib
[Protocols]
gEfiTcp4ServiceBindingProtocolGuid ## BY_START
gEfiIp4ServiceBindingProtocolGuid ## TO_START
gEfiTcp4ProtocolGuid ## BY_START
gEfiIp4ProtocolGuid ## TO_START
[UserExtensions.TianoCore."ExtraFiles"]
Tcp4DxeExtra.uni

View File

@ -1,23 +0,0 @@
// /** @file
// This module produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol.
//
// This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol
// upon EFI IPv4 Protocol, to provide basic TCPv4 I/O services.
//
// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
//
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol"
#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol upon EFI IPv4 Protocol to provide basic TCPv4 I/O services."

View File

@ -1,20 +0,0 @@
// /** @file
// Tcp4Dxe Localized Strings and Content
//
// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
//
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"TCP v4 DXE Driver"

View File

@ -1,781 +0,0 @@
/** @file
Tcp function header file.
Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TCP4_FUNC_H_
#define _TCP4_FUNC_H_
//
// Declaration of all the functions in TCP
// protocol. It is intended to keep tcp.h
// clear.
//
//
// Functions in tcp.c
//
/**
Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
@param Addr Pointer to the IP address needs to match.
@param Port The port number needs to match.
@return The Tcb which matches the <Addr Port> paire exists or not.
**/
BOOLEAN
TcpFindTcbByPeer (
IN EFI_IPv4_ADDRESS *Addr,
IN TCP_PORTNO Port
);
/**
Locate the TCP_CB related to the socket pair.
@param LocalPort The local port number.
@param LocalIp The local IP address.
@param RemotePort The remote port number.
@param RemoteIp The remote IP address.
@param Syn Whether to search the listen sockets, if TRUE, the
listen sockets are searched.
@return Pointer to the related TCP_CB, if NULL no match is found.
**/
TCP_CB *
TcpLocateTcb (
IN TCP_PORTNO LocalPort,
IN UINT32 LocalIp,
IN TCP_PORTNO RemotePort,
IN UINT32 RemoteIp,
IN BOOLEAN Syn
);
/**
Insert a Tcb into the proper queue.
@param Tcb Pointer to the TCP_CB to be inserted.
@retval 0 The Tcb is inserted successfully.
@retval -1 Error condition occurred.
**/
INTN
TcpInsertTcb (
IN TCP_CB *Tcb
);
/**
Clone a TCP_CB from Tcb.
@param Tcb Pointer to the TCP_CB to be cloned.
@return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
**/
TCP_CB *
TcpCloneTcb (
IN TCP_CB *Tcb
);
/**
Compute an ISS to be used by a new connection.
@return The result ISS.
**/
TCP_SEQNO
TcpGetIss (
VOID
);
/**
Initialize the Tcb local related members.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
);
/**
Initialize the peer related members.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seg Pointer to the segment that contains the peer's
intial info.
@param Opt Pointer to the options announced by the peer.
**/
VOID
TcpInitTcbPeer (
IN OUT TCP_CB *Tcb,
IN TCP_SEG *Seg,
IN TCP_OPTION *Opt
);
/**
Get the local mss.
@param Sock Pointer to the socket to get mss
@return The mss size.
**/
UINT16
TcpGetRcvMss (
IN SOCKET *Sock
);
/**
Set the Tcb's state.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param State The state to be set.
**/
VOID
TcpSetState (
IN OUT TCP_CB *Tcb,
IN UINT8 State
);
//
// Functions in Tcp4Output.c
//
/**
Send the segment to IP via IpIo function.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the TCP segment to be sent.
@param Src Source address of the TCP segment.
@param Dest Destination address of the TCP segment.
@retval 0 The segment was sent out successfully.
@retval -1 The segment was failed to send.
**/
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dest
);
/**
Check whether to send data/SYN/FIN and piggy back an ACK.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Force Whether to ignore the sender's SWS avoidance algorithm and send
out data by force.
@return The number of bytes sent.
**/
INTN
TcpToSendData (
IN OUT TCP_CB *Tcb,
IN INTN Force
);
/**
Check whether to send an ACK or delayed ACK.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpToSendAck (
IN OUT TCP_CB *Tcb
);
/**
Send an ACK immediately.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpSendAck (
IN OUT TCP_CB *Tcb
);
/**
Send a zero probe segment. It can be used by keepalive and zero window probe.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@retval 0 The zero probe segment was sent out successfully.
@retval other Error condition occurred.
**/
INTN
TcpSendZeroProbe (
IN OUT TCP_CB *Tcb
);
/**
Process the data and FIN flag, check whether to deliver
data to the socket layer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@retval 0 No error occurred to deliver data.
@retval -1 Error condition occurred. Proper response is to reset the
connection.
**/
INTN
TcpDeliverData (
IN OUT TCP_CB *Tcb
);
/**
Send a RESET segment in response to the segment received.
@param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.
@param Head TCP header of the segment that triggers the reset.
@param Len Length of the segment that triggers the reset.
@param Local Local IP address.
@param Remote Remote peer's IP address.
@retval 0 A reset is sent or no need to send it.
@retval -1 No reset is sent.
**/
INTN
TcpSendReset (
IN TCP_CB *Tcb,
IN TCP_HEAD *Head,
IN INT32 Len,
IN UINT32 Local,
IN UINT32 Remote
);
/**
Compute the sequence space left in the old receive window.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return The sequence space left in the old receive window.
**/
UINT32
TcpRcvWinOld (
IN TCP_CB *Tcb
);
/**
Compute the current receive window.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return The size of the current receive window, in bytes.
**/
UINT32
TcpRcvWinNow (
IN TCP_CB *Tcb
);
/**
Retransmit the segment from sequence Seq.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seq The sequence number of the segment to be retransmitted.
@retval 0 Retransmission succeeded.
@retval -1 Error condition occurred.
**/
INTN
TcpRetransmit (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq
);
/**
Compute how much data to send.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Force Whether to ignore the sender's SWS avoidance algorithm and send
out data by force.
@return The length of the data can be sent, if 0, no data can be sent.
**/
UINT32
TcpDataToSend (
IN TCP_CB *Tcb,
IN INTN Force
);
/**
Verify that the segment is in good shape.
@param Nbuf Buffer that contains the segment to be checked.
@retval 0 The segment is broken.
@retval 1 The segment is in good shape.
**/
INTN
TcpVerifySegment (
IN NET_BUF *Nbuf
);
/**
Verify that all the segments in SndQue are in good shape.
@param Head Pointer to the head node of the SndQue.
@retval 0 At least one segment is broken.
@retval 1 All segments in the specific queue are in good shape.
**/
INTN
TcpCheckSndQue (
IN LIST_ENTRY *Head
);
/**
Get a segment from the Tcb's SndQue.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seq The sequence number of the segment.
@param Len The maximum length of the segment.
@return Pointer to the segment, if NULL some error occurred.
**/
NET_BUF *
TcpGetSegmentSndQue (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
/**
Get a segment from the Tcb's socket buffer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seq The sequence number of the segment.
@param Len The maximum length of the segment.
@return Pointer to the segment, if NULL some error occurred.
**/
NET_BUF *
TcpGetSegmentSock (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
/**
Get a segment starting from sequence Seq of a maximum
length of Len.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seq The sequence number of the segment.
@param Len The maximum length of the segment.
@return Pointer to the segment, if NULL some error occurred.
**/
NET_BUF *
TcpGetSegment (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
/**
Get the maximum SndNxt.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return The sequence number of the maximum SndNxt.
**/
TCP_SEQNO
TcpGetMaxSndNxt (
IN TCP_CB *Tcb
);
//
// Functions from Tcp4Input.c
//
/**
Process the received ICMP error messages for TCP.
@param Nbuf Buffer that contains part of the TCP segment without IP header
truncated from the ICMP error packet.
@param IcmpErr The ICMP error code interpreted from ICMP error packet.
@param Src Source address of the ICMP error message.
@param Dst Destination address of the ICMP error message.
**/
VOID
TcpIcmpInput (
IN NET_BUF *Nbuf,
IN UINT8 IcmpErr,
IN UINT32 Src,
IN UINT32 Dst
);
/**
Process the received TCP segments.
@param Nbuf Buffer that contains received TCP segment without IP header.
@param Src Source address of the segment, or the peer's IP address.
@param Dst Destination address of the segment, or the local end's IP
address.
@retval 0 Segment is processed successfully. It is either accepted or
discarded. But no connection is reset by the segment.
@retval -1 A connection is reset by the segment.
**/
INTN
TcpInput (
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dst
);
/**
Check whether the sequence number of the incoming segment is acceptable.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seg Pointer to the incoming segment.
@retval 1 The sequence number is acceptable.
@retval 0 The sequence number is not acceptable.
**/
INTN
TcpSeqAcceptable (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg
);
/**
NewReno fast recovery, RFC3782.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seg Segment that triggers the fast recovery.
**/
VOID
TcpFastRecover (
IN OUT TCP_CB *Tcb,
IN TCP_SEG *Seg
);
/**
NewReno fast loss recovery, RFC3792.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seg Segment that triggers the fast loss recovery.
**/
VOID
TcpFastLossRecover (
IN OUT TCP_CB *Tcb,
IN TCP_SEG *Seg
);
/**
Compute the RTT as specified in RFC2988.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Measure Currently measured RTT in heart beats.
**/
VOID
TcpComputeRtt (
IN OUT TCP_CB *Tcb,
IN UINT32 Measure
);
/**
Trim off the data outside the tcb's receive window.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the NET_BUF containing the received tcp segment.
**/
VOID
TcpTrimInWnd (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
/**
Store the data into the reassemble queue.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer containing the data to be queued.
**/
VOID
TcpQueueData (
IN OUT TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
/**
Ajust the send queue or the retransmit queue.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Ack The acknowledge seuqence number of the received segment.
**/
VOID
TcpAdjustSndQue (
IN TCP_CB *Tcb,
IN TCP_SEQNO Ack
);
//
// Functions from Tcp4Misc.c
//
/**
Compute the TCP segment's checksum.
@param Nbuf Pointer to the buffer that contains the TCP
segment.
@param HeadSum The checksum value of the fixed part of pseudo
header.
@return The checksum value.
**/
UINT16
TcpChecksum (
IN NET_BUF *Nbuf,
IN UINT16 HeadSum
);
/**
Translate the information from the head of the received TCP
segment Nbuf contains and fill it into a TCP_SEG structure.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer contains the TCP segment.
@return Pointer to the TCP_SEG that contains the translated TCP head information.
**/
TCP_SEG *
TcpFormatNetbuf (
IN TCP_CB *Tcb,
IN OUT NET_BUF *Nbuf
);
/**
Initialize an active connection.
@param Tcb Pointer to the TCP_CB that wants to initiate a
connection.
**/
VOID
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
);
/**
Application has consumed some data, check whether
to send a window updata ack or a delayed ack.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpOnAppConsume (
IN TCP_CB *Tcb
);
/**
Initiate the connection close procedure, called when
applications want to close the connection.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpOnAppClose (
IN OUT TCP_CB *Tcb
);
/**
Check whether the application's newly delivered data can be sent out.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@retval 0 Whether the data is sent out or is buffered for
further sending.
@retval -1 The Tcb is not in a state that data is permitted to
be sent out.
**/
INTN
TcpOnAppSend (
IN OUT TCP_CB *Tcb
);
/**
Abort the connection by sending a reset segment, called
when the application wants to abort the connection.
@param Tcb Pointer to the TCP_CB of the TCP instance.
**/
VOID
TcpOnAppAbort (
IN TCP_CB *Tcb
);
/**
Reset the connection related with Tcb.
@param Tcb Pointer to the TCP_CB of the connection to be
reset.
**/
VOID
TcpResetConnection (
IN TCP_CB *Tcb
);
//
// Functions in Tcp4Timer.c
//
/**
Close the TCP connection.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpClose (
IN OUT TCP_CB *Tcb
);
/**
Heart beat timer handler, queues the DPC at TPL_CALLBACK.
@param Event Timer event signaled, ignored.
@param Context Context of the timer event, ignored.
**/
VOID
EFIAPI
TcpTicking (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
Enable a TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be enabled.
@param TimeOut The timeout value of this timer.
**/
VOID
TcpSetTimer (
IN OUT TCP_CB *Tcb,
IN UINT16 Timer,
IN UINT32 TimeOut
);
/**
Clear one TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be cleared.
**/
VOID
TcpClearTimer (
IN OUT TCP_CB *Tcb,
IN UINT16 Timer
);
/**
Clear all TCP timers.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpClearAllTimer (
IN OUT TCP_CB *Tcb
);
/**
Enable the window prober timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpSetProbeTimer (
IN OUT TCP_CB *Tcb
);
/**
Enable the keepalive timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpSetKeepaliveTimer (
IN OUT TCP_CB *Tcb
);
/**
Backoff the RTO.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpBackoffRto (
IN OUT TCP_CB *Tcb
);
/**
Install the device path protocol on the TCP instance.
@param Sock Pointer to the socket representing the TCP instance.
@retval EFI_SUCCESS The device path protocol is installed.
@retval other Failed to install the device path protocol.
**/
EFI_STATUS
TcpInstallDevicePath (
IN SOCKET *Sock
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,112 +0,0 @@
/** @file
I/O interfaces between TCP and IpIo.
Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
/**
Packet receive callback function provided to IP_IO, used to call
the proper function to handle the packet received by IP.
@param Status Status of the received packet.
@param IcmpErr ICMP error number.
@param NetSession Pointer to the net session of this packet.
@param Pkt Pointer to the recieved packet.
@param Context Pointer to the context configured in IpIoOpen(), not used
now.
**/
VOID
EFIAPI
Tcp4RxCallback (
IN EFI_STATUS Status,
IN UINT8 IcmpErr,
IN EFI_NET_SESSION_DATA *NetSession,
IN NET_BUF *Pkt,
IN VOID *Context OPTIONAL
)
{
if (EFI_SUCCESS == Status) {
TcpInput (Pkt, NetSession->Source.Addr[0], NetSession->Dest.Addr[0]);
} else {
TcpIcmpInput (Pkt, IcmpErr, NetSession->Source.Addr[0], NetSession->Dest.Addr[0]);
}
}
/**
Send the segment to IP via IpIo function.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the TCP segment to be sent.
@param Src Source address of the TCP segment.
@param Dest Destination address of the TCP segment.
@retval 0 The segment was sent out successfully.
@retval -1 The segment was failed to send.
**/
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dest
)
{
EFI_STATUS Status;
IP_IO *IpIo;
IP_IO_OVERRIDE Override;
SOCKET *Sock;
VOID *IpSender;
TCP4_PROTO_DATA *TcpProto;
EFI_IP_ADDRESS Source;
EFI_IP_ADDRESS Destination;
Source.Addr[0] = Src;
Destination.Addr[0] = Dest;
if (NULL == Tcb) {
IpIo = NULL;
IpSender = IpIoFindSender (&IpIo, IP_VERSION_4, &Source);
if (IpSender == NULL) {
DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
return -1;
}
} else {
Sock = Tcb->Sk;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
IpIo = TcpProto->TcpService->IpIo;
IpSender = Tcb->IpInfo;
}
Override.Ip4OverrideData.TypeOfService = 0;
Override.Ip4OverrideData.TimeToLive = 255;
Override.Ip4OverrideData.DoNotFragment = FALSE;
Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;
ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
CopyMem (&Override.Ip4OverrideData.SourceAddress, &Src, sizeof (EFI_IPv4_ADDRESS));
Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, &Destination, &Override);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
return -1;
}
return 0;
}

View File

@ -1,674 +0,0 @@
/** @file
Implementation of TCP4 protocol services.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
/**
Check the integrity of the data buffer.
@param DataLen The total length of the data buffer.
@param FragmentCount The fragment count of the fragment table.
@param FragmentTable Pointer to the fragment table of the data
buffer.
@retval EFI_SUCCESS The integrity check is passed.
@retval EFI_INVALID_PARAMETER The integrity check is failed.
**/
EFI_STATUS
Tcp4ChkDataBuf (
IN UINT32 DataLen,
IN UINT32 FragmentCount,
IN EFI_TCP4_FRAGMENT_DATA *FragmentTable
)
{
UINT32 Index;
UINT32 Len;
for (Index = 0, Len = 0; Index < FragmentCount; Index++) {
Len = Len + (UINT32) FragmentTable[Index].FragmentLength;
}
if (DataLen != Len) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
Get the current operational status.
The GetModeData() function copies the current operational settings of this
EFI TCPv4 Protocol instance into user-supplied buffers. This function can
also be used to retrieve the operational setting of underlying drivers
such as IPv4, MNP, or SNP.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Tcp4State Pointer to the buffer to receive the current TCP
state.
@param Tcp4ConfigData Pointer to the buffer to receive the current TCP
configuration.
@param Ip4ModeData Pointer to the buffer to receive the current IPv4
configuration data used by the TCPv4 instance.
@param MnpConfigData Pointer to the buffer to receive the current MNP
configuration data indirectly used by the TCPv4
Instance.
@param SnpModeData Pointer to the buffer to receive the current SNP
configuration data indirectly used by the TCPv4
Instance.
@retval EFI_SUCCESS The mode data was read.
@retval EFI_NOT_STARTED No configuration data is available because this
instance hasn't been started.
@retval EFI_INVALID_PARAMETER This is NULL.
**/
EFI_STATUS
EFIAPI
Tcp4GetModeData (
IN EFI_TCP4_PROTOCOL *This,
OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL,
OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
)
{
TCP4_MODE_DATA TcpMode;
SOCKET *Sock;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
TcpMode.Tcp4State = Tcp4State;
TcpMode.Tcp4ConfigData = Tcp4ConfigData;
TcpMode.Ip4ModeData = Ip4ModeData;
TcpMode.MnpConfigData = MnpConfigData;
TcpMode.SnpModeData = SnpModeData;
return SockGetMode (Sock, &TcpMode);
}
/**
Initialize or brutally reset the operational parameters for
this EFI TCPv4 instance.
The Configure() function does the following:
* Initialize this EFI TCPv4 instance, i.e., initialize the communication end
setting, specify active open or passive open for an instance.
* Reset this TCPv4 instance brutally, i.e., cancel all pending asynchronous
tokens, flush transmission and receiving buffer directly without informing
the communication peer.
No other TCPv4 Protocol operation can be executed by this instance
until it is configured properly. For an active TCP4 instance, after a proper
configuration it may call Connect() to initiates the three-way handshake.
For a passive TCP4 instance, its state will transit to Tcp4StateListen after
configuration, and Accept() may be called to listen the incoming TCP connection
request. If TcpConfigData is set to NULL, the instance is reset. Resetting
process will be done brutally, the state machine will be set to Tcp4StateClosed
directly, the receive queue and transmit queue will be flushed, and no traffic is
allowed through this instance.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param TcpConfigData Pointer to the configure data to configure the
instance.
@retval EFI_SUCCESS The operational settings are set, changed, or
reset successfully.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED Configuring TCP instance when it is already
configured.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval EFI_UNSUPPORTED One or more of the control options are not
supported in the implementation.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
**/
EFI_STATUS
EFIAPI
Tcp4Configure (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL
)
{
EFI_TCP4_OPTION *Option;
SOCKET *Sock;
EFI_STATUS Status;
IP4_ADDR Ip;
IP4_ADDR SubnetMask;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
//
// Tcp protocol related parameter check will be conducted here
//
if (NULL != TcpConfigData) {
CopyMem (&Ip, &TcpConfigData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
if (IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
return EFI_INVALID_PARAMETER;
}
if (TcpConfigData->AccessPoint.ActiveFlag &&
(0 == TcpConfigData->AccessPoint.RemotePort || (Ip == 0))) {
return EFI_INVALID_PARAMETER;
}
if (!TcpConfigData->AccessPoint.UseDefaultAddress) {
CopyMem (&Ip, &TcpConfigData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
CopyMem (&SubnetMask, &TcpConfigData->AccessPoint.SubnetMask, sizeof (IP4_ADDR));
if (!IP4_IS_VALID_NETMASK (NTOHL (SubnetMask)) ||
(SubnetMask != 0 && !NetIp4IsUnicast (NTOHL (Ip), NTOHL (SubnetMask)))) {
return EFI_INVALID_PARAMETER;
}
}
Option = TcpConfigData->ControlOption;
if ((NULL != Option) &&
(Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {
return EFI_UNSUPPORTED;
}
}
Sock = SOCK_FROM_THIS (This);
if (NULL == TcpConfigData) {
return SockFlush (Sock);
}
Status = SockConfigure (Sock, TcpConfigData);
if (EFI_NO_MAPPING == Status) {
Sock->ConfigureState = SO_NO_MAPPING;
}
return Status;
}
/**
Add or delete routing entries.
The Routes() function adds or deletes a route from the instance's routing table.
The most specific route is selected by comparing the SubnetAddress with the
destination IP address's arithmetical AND to the SubnetMask.
The default route is added with both SubnetAddress and SubnetMask set to 0.0.0.0.
The default route matches all destination IP addresses if there is no more specific route.
Direct route is added with GatewayAddress set to 0.0.0.0. Packets are sent to
the destination host if its address can be found in the Address Resolution Protocol (ARP)
cache or it is on the local subnet. If the instance is configured to use default
address, a direct route to the local network will be added automatically.
Each TCP instance has its own independent routing table. Instance that uses the
default IP address will have a copy of the EFI_IP4_CONFIG_PROTOCOL's routing table.
The copy will be updated automatically whenever the IP driver reconfigures its
instance. As a result, the previous modification to the instance's local copy
will be lost. The priority of checking the route table is specific with IP
implementation and every IP implementation must comply with RFC 1122.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param DeleteRoute If TRUE, delete the specified route from routing
table; if FALSE, add the specified route to
routing table.
DestinationAddress and SubnetMask are used as
the keywords to search route entry.
@param SubnetAddress The destination network.
@param SubnetMask The subnet mask for the destination network.
@param GatewayAddress The gateway address for this route.
It must be on the same subnet with the station
address unless a direct route is specified.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the
entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table.
@retval EFI_ACCESS_DENIED This route is already in the routing table.
@retval EFI_UNSUPPORTED The TCP driver does not support this operation.
**/
EFI_STATUS
EFIAPI
Tcp4Routes (
IN EFI_TCP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
)
{
SOCKET *Sock;
TCP4_ROUTE_INFO RouteInfo;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
RouteInfo.DeleteRoute = DeleteRoute;
RouteInfo.SubnetAddress = SubnetAddress;
RouteInfo.SubnetMask = SubnetMask;
RouteInfo.GatewayAddress = GatewayAddress;
return SockRoute (Sock, &RouteInfo);
}
/**
Initiate a nonblocking TCP connection request for an active TCP instance.
The Connect() function will initiate an active open to the remote peer configured
in current TCP instance if it is configured active. If the connection succeeds
or fails due to any error, the ConnectionToken->CompletionToken.Event will be
signaled and ConnectionToken->CompletionToken.Status will be updated accordingly.
This function can only be called for the TCP instance in Tcp4StateClosed state.
The instance will transfer into Tcp4StateSynSent if the function returns EFI_SUCCESS.
If TCP three way handshake succeeds, its state will become Tcp4StateEstablished,
otherwise, the state will return to Tcp4StateClosed.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ConnectionToken Pointer to the connection token to return when
the TCP three way handshake finishes.
@retval EFI_SUCCESS The connection request is successfully initiated
and the state of this TCPv4 instance has
been changed to Tcp4StateSynSent.
@retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instance is not configured as an active one
or it is not in Tcp4StateClosed state.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to
initiate the active open.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
Tcp4Connect (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == ConnectionToken ||
NULL == ConnectionToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockConnect (Sock, ConnectionToken);
}
/**
Listen on the passive instance to accept an incoming connection request.
The Accept() function initiates an asynchronous accept request to wait for an
incoming connection on the passive TCP instance. If a remote peer successfully
establishes a connection with this instance, a new TCP instance will be created
and its handle will be returned in ListenToken->NewChildHandle. The newly created
instance is configured by inheriting the passive instance's configuration and is
ready for use upon return. The instance is in the Tcp4StateEstablished state.
The ListenToken->CompletionToken.Event will be signaled when a new connection
is accepted, user aborts the listen or connection is reset. This function only
can be called when current TCP instance is in Tcp4StateListen state.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ListenToken Pointer to the listen token to return when
operation finishes.
@retval EFI_SUCCESS The listen token has been queued successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not
in Tcp4StateListen state or a same listen token
has already existed in the listen token queue of
this TCP instance.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish
the operation.
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.
**/
EFI_STATUS
EFIAPI
Tcp4Accept (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == ListenToken ||
NULL == ListenToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockAccept (Sock, ListenToken);
}
/**
Queues outgoing data into the transmit queue.
The Transmit() function queues a sending request to this TCPv4 instance along
with the user data. The status of the token is updated and the event in the token
will be signaled once the data is sent out or some error occurs.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param Token Pointer to the completion token to queue to the
transmit queue
@retval EFI_SUCCESS The data has been queued for transmission.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A transmit completion token with the same
Token-> CompletionToken.Event was already in the
transmission queue.
* The current instance is in Tcp4StateClosed state
* The current instance is a passive one and
it is in Tcp4StateListen state.
* User has called Close() to disconnect this
connection.
@retval EFI_NOT_READY The completion token could not be queued because
the transmit queue is full.
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of
resource shortage.
@retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or
address.
**/
EFI_STATUS
EFIAPI
Tcp4Transmit (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This ||
NULL == Token ||
NULL == Token->CompletionToken.Event ||
NULL == Token->Packet.TxData ||
0 == Token->Packet.TxData->FragmentCount ||
0 == Token->Packet.TxData->DataLength
) {
return EFI_INVALID_PARAMETER;
}
Status = Tcp4ChkDataBuf (
(UINT32) Token->Packet.TxData->DataLength,
(UINT32) Token->Packet.TxData->FragmentCount,
Token->Packet.TxData->FragmentTable
);
if (EFI_ERROR (Status)) {
return Status;
}
Sock = SOCK_FROM_THIS (This);
return SockSend (Sock, Token);
}
/**
Place an asynchronous receive request into the receiving queue.
The Receive() function places a completion token into the receive packet queue.
This function is always asynchronous. The caller must allocate the
Token->CompletionToken.Event and the FragmentBuffer used to receive data. He also
must fill the DataLength which represents the whole length of all FragmentBuffer.
When the receive operation completes, the EFI TCPv4 Protocol driver updates the
Token->CompletionToken.Status and Token->Packet.RxData fields and the
Token->CompletionToken.Event is signaled. If got data the data and its length
will be copy into the FragmentTable, in the same time the full length of received
data will be recorded in the DataLength fields. Providing a proper notification
function and context for the event will enable the user to receive the notification
and receiving status. That notification function is guaranteed to not be re-entered.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that is associated with the
receive data descriptor.
@retval EFI_SUCCESS The receive completion token was cached.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
due to a lack of system resources.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The EFI TCPv4 Protocol instance has been reset
to startup defaults.
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A receive completion token with the same
Token->CompletionToken.Event was already in
the receive queue.
* The current instance is in Tcp4StateClosed state.
* The current instance is a passive one and it
is in Tcp4StateListen state.
* User has called Close() to disconnect this
connection.
@retval EFI_CONNECTION_FIN The communication peer has closed the connection
and there is no any buffered data in the receive
buffer of this instance.
@retval EFI_NOT_READY The receive request could not be queued because
the receive queue is full.
**/
EFI_STATUS
EFIAPI
Tcp4Receive (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This ||
NULL == Token ||
NULL == Token->CompletionToken.Event ||
NULL == Token->Packet.RxData ||
0 == Token->Packet.RxData->FragmentCount ||
0 == Token->Packet.RxData->DataLength
) {
return EFI_INVALID_PARAMETER;
}
Status = Tcp4ChkDataBuf (
(UINT32) Token->Packet.RxData->DataLength,
(UINT32) Token->Packet.RxData->FragmentCount,
Token->Packet.RxData->FragmentTable
);
if (EFI_ERROR (Status)) {
return Status;
}
Sock = SOCK_FROM_THIS (This);
return SockRcv (Sock, Token);
}
/**
Disconnecting a TCP connection gracefully or reset a TCP connection.
Initiate an asynchronous close token to TCP driver. After Close() is called,
any buffered transmission data will be sent by TCP driver and the current
instance will have a graceful close working flow described as RFC 793 if
AbortOnClose is set to FALSE, otherwise, a rest packet will be sent by TCP
driver to fast disconnect this connection. When the close operation completes
successfully the TCP instance is in Tcp4StateClosed state, all pending
asynchronous operation is signaled and any buffers used for TCP network traffic
is flushed.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param CloseToken Pointer to the close token to return when
operation finishes.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED One or more of the following are TRUE:
* Configure() has been called with TcpConfigData
set to NULL and this function has not returned.
* Previous Close() call on this instance has not
finished.
@retval EFI_INVALID_PARAMETER One ore more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the
operation.
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above
category error.
**/
EFI_STATUS
EFIAPI
Tcp4Close (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == CloseToken ||
NULL == CloseToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);
}
/**
Abort an asynchronous connection, listen, transmission or receive request.
The Cancel() function aborts a pending connection, listen, transmit or receive
request. If Token is not NULL and the token is in the connection, listen,
transmission or receive queue when it is being cancelled, its Token->Status
will be set to EFI_ABORTED and then Token->Event will be signaled. If the token
is not in one of the queues, which usually means that the asynchronous operation
has completed, EFI_NOT_FOUND is returned. If Token is NULL all asynchronous token
issued by Connect(), Accept(), Transmit() and Receive()will be aborted.
NOTE: It has not been implemented currently.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by above four
functions will be aborted.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn's been configured.
@retval EFI_NO_MAPPING When using the default address, configuration
(DHCP, BOOTP,RARP, etc.) hasn's finished yet.
@retval EFI_NOT_FOUND The asynchronous I/O request isn's found in the
transmission or receive queue. It has either
completed or wasn's issued by Transmit() and Receive().
@retval EFI_UNSUPPORTED The operation is not supported in current
implementation.
**/
EFI_STATUS
EFIAPI
Tcp4Cancel (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL
)
{
return EFI_UNSUPPORTED;
}
/**
Poll to receive incoming data and transmit outgoing segments.
The Poll() function increases the rate that data is moved between the network
and application and can be called when the TCP instance is created successfully.
Its use is optional. In some implementations, the periodical timer in the MNP
driver may not poll the underlying communications device fast enough to avoid
drop packets. Drivers and applications that are experiencing packet loss should
try calling the Poll() function in a high frequency.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_NOT_READY No incoming or outgoing data was processed.
@retval EFI_TIMEOUT Data was dropped out of the transmission or
receive queue. Consider increasing the polling
rate.
**/
EFI_STATUS
EFIAPI
Tcp4Poll (
IN EFI_TCP4_PROTOCOL *This
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);
return Status;
}

View File

@ -1,494 +0,0 @@
/** @file
TCP4 protocol services header file.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TCP4_MAIN_H_
#define _TCP4_MAIN_H_
#include "Socket.h"
#include "Tcp4Proto.h"
#include "Tcp4Func.h"
#include "Tcp4Driver.h"
extern UINT16 mTcp4RandomPort;
extern CHAR16 *mTcpStateName[];
//
// Driver Produced Protocol Prototypes
//
//
// Function prototype for the Tcp4 socket request handler
//
/**
The procotol handler provided to the socket layer, used to
dispatch the socket level requests by calling the corresponding
TCP layer functions.
@param Sock Pointer to the socket of this TCP instance.
@param Request The code of this operation request.
@param Data Pointer to the operation specific data passed in
together with the operation request.
@retval EFI_SUCCESS The socket request is completed successfully.
@retval other The error status returned by the corresponding TCP
layer function.
**/
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN UINT8 Request,
IN VOID *Data OPTIONAL
);
///
/// TCP mode data
///
typedef struct _TCP4_MODE_DATA {
EFI_TCP4_CONNECTION_STATE *Tcp4State;
EFI_TCP4_CONFIG_DATA *Tcp4ConfigData;
EFI_IP4_MODE_DATA *Ip4ModeData;
EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData;
EFI_SIMPLE_NETWORK_MODE *SnpModeData;
} TCP4_MODE_DATA;
///
/// TCP route infomation data
///
typedef struct _TCP4_ROUTE_INFO {
BOOLEAN DeleteRoute;
EFI_IPv4_ADDRESS *SubnetAddress;
EFI_IPv4_ADDRESS *SubnetMask;
EFI_IPv4_ADDRESS *GatewayAddress;
} TCP4_ROUTE_INFO;
typedef struct {
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
UINTN NumberOfChildren;
EFI_HANDLE *ChildHandleBuffer;
} TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
/**
Get the current operational status of a TCP instance.
The GetModeData() function copies the current operational settings of this
EFI TCPv4 Protocol instance into user-supplied buffers. This function can
also be used to retrieve the operational setting of underlying drivers
such as IPv4, MNP, or SNP.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Tcp4State Pointer to the buffer to receive the current TCP
state.
@param Tcp4ConfigData Pointer to the buffer to receive the current TCP
configuration.
@param Ip4ModeData Pointer to the buffer to receive the current IPv4
configuration data used by the TCPv4 instance.
@param MnpConfigData Pointer to the buffer to receive the current MNP
configuration data indirectly used by the TCPv4
Instance.
@param SnpModeData Pointer to the buffer to receive the current SNP
configuration data indirectly used by the TCPv4
Instance.
@retval EFI_SUCCESS The mode data was read.
@retval EFI_NOT_STARTED No configuration data is available because this
instance hasn't been started.
@retval EFI_INVALID_PARAMETER This is NULL.
**/
EFI_STATUS
EFIAPI
Tcp4GetModeData (
IN EFI_TCP4_PROTOCOL *This,
OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL,
OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
);
/**
Initialize or brutally reset the operational parameters for
this EFI TCPv4 instance.
The Configure() function does the following:
* Initialize this EFI TCPv4 instance, i.e., initialize the communication end
setting, specify active open or passive open for an instance.
* Reset this TCPv4 instance brutally, i.e., cancel all pending asynchronous
tokens, flush transmission and receiving buffer directly without informing
the communication peer.
No other TCPv4 Protocol operation can be executed by this instance
until it is configured properly. For an active TCP4 instance, after a proper
configuration it may call Connect() to initiates the three-way handshake.
For a passive TCP4 instance, its state will transit to Tcp4StateListen after
configuration, and Accept() may be called to listen the incoming TCP connection
request. If TcpConfigData is set to NULL, the instance is reset. Resetting
process will be done brutally, the state machine will be set to Tcp4StateClosed
directly, the receive queue and transmit queue will be flushed, and no traffic is
allowed through this instance.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param TcpConfigData Pointer to the configure data to configure the
instance.
@retval EFI_SUCCESS The operational settings are set, changed, or
reset successfully.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED Configuring TCP instance when it is already
configured.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval EFI_UNSUPPORTED One or more of the control options are not
supported in the implementation.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
**/
EFI_STATUS
EFIAPI
Tcp4Configure (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL
);
/**
Add or delete routing entries.
The Routes() function adds or deletes a route from the instance's routing table.
The most specific route is selected by comparing the SubnetAddress with the
destination IP address's arithmetical AND to the SubnetMask.
The default route is added with both SubnetAddress and SubnetMask set to 0.0.0.0.
The default route matches all destination IP addresses if there is no more specific route.
Direct route is added with GatewayAddress set to 0.0.0.0. Packets are sent to
the destination host if its address can be found in the Address Resolution Protocol (ARP)
cache or it is on the local subnet. If the instance is configured to use default
address, a direct route to the local network will be added automatically.
Each TCP instance has its own independent routing table. Instance that uses the
default IP address will have a copy of the EFI_IP4_CONFIG_PROTOCOL's routing table.
The copy will be updated automatically whenever the IP driver reconfigures its
instance. As a result, the previous modification to the instance's local copy
will be lost. The priority of checking the route table is specific with IP
implementation and every IP implementation must comply with RFC 1122.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param DeleteRoute If TRUE, delete the specified route from routing
table; if FALSE, add the specified route to
routing table.
DestinationAddress and SubnetMask are used as
the keywords to search route entry.
@param SubnetAddress The destination network.
@param SubnetMask The subnet mask for the destination network.
@param GatewayAddress The gateway address for this route.
It must be on the same subnet with the station
address unless a direct route is specified.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the
entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table.
@retval EFI_ACCESS_DENIED This route is already in the routing table.
@retval EFI_UNSUPPORTED The TCP driver does not support this operation.
**/
EFI_STATUS
EFIAPI
Tcp4Routes (
IN EFI_TCP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
);
/**
Initiate a nonblocking TCP connection request for an active TCP instance.
The Connect() function will initiate an active open to the remote peer configured
in current TCP instance if it is configured active. If the connection succeeds
or fails due to any error, the ConnectionToken->CompletionToken.Event will be
signaled and ConnectionToken->CompletionToken.Status will be updated accordingly.
This function can only be called for the TCP instance in Tcp4StateClosed state.
The instance will transfer into Tcp4StateSynSent if the function returns EFI_SUCCESS.
If TCP three way handshake succeeds, its state will become Tcp4StateEstablished,
otherwise, the state will return to Tcp4StateClosed.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ConnectionToken Pointer to the connection token to return when
the TCP three way handshake finishes.
@retval EFI_SUCCESS The connection request is successfully initiated
and the state of this TCPv4 instance has
been changed to Tcp4StateSynSent.
@retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instance is not configured as an active one
or it is not in Tcp4StateClosed state.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to
initiate the active open.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
Tcp4Connect (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
);
/**
Listen on the passive instance to accept an incoming connection request.
The Accept() function initiates an asynchronous accept request to wait for an
incoming connection on the passive TCP instance. If a remote peer successfully
establishes a connection with this instance, a new TCP instance will be created
and its handle will be returned in ListenToken->NewChildHandle. The newly created
instance is configured by inheriting the passive instance's configuration and is
ready for use upon return. The instance is in the Tcp4StateEstablished state.
The ListenToken->CompletionToken.Event will be signaled when a new connection
is accepted, user aborts the listen or connection is reset. This function only
can be called when current TCP instance is in Tcp4StateListen state.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ListenToken Pointer to the listen token to return when
operation finishes.
@retval EFI_SUCCESS The listen token has been queued successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not
in Tcp4StateListen state or a same listen token
has already existed in the listen token queue of
this TCP instance.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish
the operation.
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.
**/
EFI_STATUS
EFIAPI
Tcp4Accept (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
);
/**
Queues outgoing data into the transmit queue.
The Transmit() function queues a sending request to this TCPv4 instance along
with the user data. The status of the token is updated and the event in the token
will be signaled once the data is sent out or some error occurs.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param Token Pointer to the completion token to queue to the
transmit queue
@retval EFI_SUCCESS The data has been queued for transmission.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A transmit completion token with the same
Token-> CompletionToken.Event was already in the
transmission queue.
* The current instance is in Tcp4StateClosed state
* The current instance is a passive one and
it is in Tcp4StateListen state.
* User has called Close() to disconnect this
connection.
@retval EFI_NOT_READY The completion token could not be queued because
the transmit queue is full.
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of
resource shortage.
@retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or
address.
**/
EFI_STATUS
EFIAPI
Tcp4Transmit (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
);
/**
Place an asynchronous receive request into the receiving queue.
The Receive() function places a completion token into the receive packet queue.
This function is always asynchronous. The caller must allocate the
Token->CompletionToken.Event and the FragmentBuffer used to receive data. He also
must fill the DataLength which represents the whole length of all FragmentBuffer.
When the receive operation completes, the EFI TCPv4 Protocol driver updates the
Token->CompletionToken.Status and Token->Packet.RxData fields and the
Token->CompletionToken.Event is signaled. If got data the data and its length
will be copy into the FragmentTable, in the same time the full length of received
data will be recorded in the DataLength fields. Providing a proper notification
function and context for the event will enable the user to receive the notification
and receiving status. That notification function is guaranteed to not be re-entered.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that is associated with the
receive data descriptor.
@retval EFI_SUCCESS The receive completion token was cached.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
due to a lack of system resources.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The EFI TCPv4 Protocol instance has been reset
to startup defaults.
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A receive completion token with the same
Token->CompletionToken.Event was already in
the receive queue.
* The current instance is in Tcp4StateClosed state.
* The current instance is a passive one and it
is in Tcp4StateListen state.
* User has called Close() to disconnect this
connection.
@retval EFI_CONNECTION_FIN The communication peer has closed the connection
and there is no any buffered data in the receive
buffer of this instance.
@retval EFI_NOT_READY The receive request could not be queued because
the receive queue is full.
**/
EFI_STATUS
EFIAPI
Tcp4Receive (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
);
/**
Disconnecting a TCP connection gracefully or reset a TCP connection.
Initiate an asynchronous close token to TCP driver. After Close() is called,
any buffered transmission data will be sent by TCP driver and the current
instance will have a graceful close working flow described as RFC 793 if
AbortOnClose is set to FALSE, otherwise, a rest packet will be sent by TCP
driver to fast disconnect this connection. When the close operation completes
successfully the TCP instance is in Tcp4StateClosed state, all pending
asynchronous operation is signaled and any buffers used for TCP network traffic
is flushed.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param CloseToken Pointer to the close token to return when
operation finishes.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED One or more of the following are TRUE:
* Configure() has been called with TcpConfigData
set to NULL and this function has not returned.
* Previous Close() call on this instance has not
finished.
@retval EFI_INVALID_PARAMETER One ore more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the
operation.
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above
category error.
**/
EFI_STATUS
EFIAPI
Tcp4Close (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
);
/**
Abort an asynchronous connection, listen, transmission or receive request.
The Cancel() function aborts a pending connection, listen, transmit or receive
request. If Token is not NULL and the token is in the connection, listen,
transmission or receive queue when it is being cancelled, its Token->Status
will be set to EFI_ABORTED and then Token->Event will be signaled. If the token
is not in one of the queues, which usually means that the asynchronous operation
has completed, EFI_NOT_FOUND is returned. If Token is NULL all asynchronous token
issued by Connect(), Accept(), Transmit() and Receive()will be aborted.
NOTE: It has not been implemented currently.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by above four
functions will be aborted.
@retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event
is signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance hasn's been configured.
@retval EFI_NO_MAPPING When using the default address, configuration
(DHCP, BOOTP,RARP, etc.) hasn's finished yet.
@retval EFI_NOT_FOUND The asynchronous I/O request isn's found in the
transmission or receive queue. It has either
completed or wasn's issued by Transmit() and Receive().
@retval EFI_UNSUPPORTED The operation is not supported in current
implementation.
**/
EFI_STATUS
EFIAPI
Tcp4Cancel (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL
);
/**
Poll to receive incoming data and transmit outgoing segments.
The Poll() function increases the rate that data is moved between the network
and application and can be called when the TCP instance is created successfully.
Its use is optional. In some implementations, the periodical timer in the MNP
driver may not poll the underlying communications device fast enough to avoid
drop packets. Drivers and applications that are experiencing packet loss should
try calling the Poll() function in a high frequency.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_NOT_READY No incoming or outgoing data was processed.
@retval EFI_TIMEOUT Data was dropped out of the transmission or
receive queue. Consider increasing the polling
rate.
**/
EFI_STATUS
EFIAPI
Tcp4Poll (
IN EFI_TCP4_PROTOCOL *This
);
#endif

View File

@ -1,940 +0,0 @@
/** @file
Misc support routines for tcp.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
#include <Library/DevicePathLib.h>
LIST_ENTRY mTcpRunQue = {
&mTcpRunQue,
&mTcpRunQue
};
LIST_ENTRY mTcpListenQue = {
&mTcpListenQue,
&mTcpListenQue
};
TCP_SEQNO mTcpGlobalIss = 0x4d7e980b;
CHAR16 *mTcpStateName[] = {
L"TCP_CLOSED",
L"TCP_LISTEN",
L"TCP_SYN_SENT",
L"TCP_SYN_RCVD",
L"TCP_ESTABLISHED",
L"TCP_FIN_WAIT_1",
L"TCP_FIN_WAIT_2",
L"TCP_CLOSING",
L"TCP_TIME_WAIT",
L"TCP_CLOSE_WAIT",
L"TCP_LAST_ACK"
};
/**
Initialize the Tcb local related members.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
)
{
//
// Compute the checksum of the fixed parts of pseudo header
//
Tcb->HeadSum = NetPseudoHeadChecksum (
Tcb->LocalEnd.Ip,
Tcb->RemoteEnd.Ip,
0x06,
0
);
Tcb->Iss = TcpGetIss ();
Tcb->SndUna = Tcb->Iss;
Tcb->SndNxt = Tcb->Iss;
Tcb->SndWl2 = Tcb->Iss;
Tcb->SndWnd = 536;
Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk);
//
// First window size is never scaled
//
Tcb->RcvWndScale = 0;
Tcb->RetxmitSeqMax = 0;
Tcb->ProbeTimerOn = FALSE;
}
/**
Initialize the peer related members.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Seg Pointer to the segment that contains the peer's
intial info.
@param Opt Pointer to the options announced by the peer.
**/
VOID
TcpInitTcbPeer (
IN OUT TCP_CB *Tcb,
IN TCP_SEG *Seg,
IN TCP_OPTION *Opt
)
{
UINT16 RcvMss;
ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL));
ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN));
Tcb->SndWnd = Seg->Wnd;
Tcb->SndWndMax = Tcb->SndWnd;
Tcb->SndWl1 = Seg->Seq;
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
Tcb->SndWl2 = Seg->Ack;
} else {
Tcb->SndWl2 = Tcb->Iss + 1;
}
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) {
Tcb->SndMss = (UINT16) MAX (64, Opt->Mss);
RcvMss = TcpGetRcvMss (Tcb->Sk);
if (Tcb->SndMss > RcvMss) {
Tcb->SndMss = RcvMss;
}
} else {
//
// One end doesn't support MSS option, use default.
//
Tcb->RcvMss = 536;
}
Tcb->CWnd = Tcb->SndMss;
Tcb->Irs = Seg->Seq;
Tcb->RcvNxt = Tcb->Irs + 1;
Tcb->RcvWl2 = Tcb->RcvNxt;
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) &&
!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) {
Tcb->SndWndScale = Opt->WndScale;
Tcb->RcvWndScale = TcpComputeScale (Tcb);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS);
} else {
//
// One end doesn't support window scale option. use zero.
//
Tcb->RcvWndScale = 0;
}
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) &&
!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS);
Tcb->TsRecent = Opt->TSVal;
//
// Compute the effective SndMss per RFC1122
// section 4.2.2.6. If timestamp option is
// enabled, it will always occupy 12 bytes.
//
Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN;
}
}
/**
Locate a listen TCB that matchs the Local and Remote.
@param Local Pointer to the local (IP, Port).
@param Remote Pointer to the remote (IP, Port).
@return Pointer to the TCP_CB with the least number of wildcard,
if NULL no match is found.
**/
TCP_CB *
TcpLocateListenTcb (
IN TCP_PEER *Local,
IN TCP_PEER *Remote
)
{
LIST_ENTRY *Entry;
TCP_CB *Node;
TCP_CB *Match;
INTN Last;
INTN Cur;
Last = 4;
Match = NULL;
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if ((Local->Port != Node->LocalEnd.Port) ||
!TCP_PEER_MATCH (Remote, &Node->RemoteEnd) ||
!TCP_PEER_MATCH (Local, &Node->LocalEnd)) {
continue;
}
//
// Compute the number of wildcard
//
Cur = 0;
if (Node->RemoteEnd.Ip == 0) {
Cur++;
}
if (Node->RemoteEnd.Port == 0) {
Cur++;
}
if (Node->LocalEnd.Ip == 0) {
Cur++;
}
if (Cur < Last) {
if (Cur == 0) {
return Node;
}
Last = Cur;
Match = Node;
}
}
return Match;
}
/**
Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
@param Addr Pointer to the IP address needs to match.
@param Port The port number needs to match.
@return The Tcb which matches the <Addr Port> paire exists or not.
**/
BOOLEAN
TcpFindTcbByPeer (
IN EFI_IPv4_ADDRESS *Addr,
IN TCP_PORTNO Port
)
{
TCP_PORTNO LocalPort;
LIST_ENTRY *Entry;
TCP_CB *Tcb;
ASSERT ((Addr != NULL) && (Port != 0));
LocalPort = HTONS (Port);
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) &&
(LocalPort == Tcb->LocalEnd.Port)) {
return TRUE;
}
}
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) &&
(LocalPort == Tcb->LocalEnd.Port)) {
return TRUE;
}
}
return FALSE;
}
/**
Locate the TCP_CB related to the socket pair.
@param LocalPort The local port number.
@param LocalIp The local IP address.
@param RemotePort The remote port number.
@param RemoteIp The remote IP address.
@param Syn Whether to search the listen sockets, if TRUE, the
listen sockets are searched.
@return Pointer to the related TCP_CB, if NULL no match is found.
**/
TCP_CB *
TcpLocateTcb (
IN TCP_PORTNO LocalPort,
IN UINT32 LocalIp,
IN TCP_PORTNO RemotePort,
IN UINT32 RemoteIp,
IN BOOLEAN Syn
)
{
TCP_PEER Local;
TCP_PEER Remote;
LIST_ENTRY *Entry;
TCP_CB *Tcb;
Local.Port = LocalPort;
Local.Ip = LocalIp;
Remote.Port = RemotePort;
Remote.Ip = RemoteIp;
//
// First check for exact match.
//
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd) &&
TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd)) {
RemoveEntryList (&Tcb->List);
InsertHeadList (&mTcpRunQue, &Tcb->List);
return Tcb;
}
}
//
// Only check listen queue when SYN flag is on
//
if (Syn) {
return TcpLocateListenTcb (&Local, &Remote);
}
return NULL;
}
/**
Insert a Tcb into the proper queue.
@param Tcb Pointer to the TCP_CB to be inserted.
@retval 0 The Tcb is inserted successfully.
@retval -1 Error condition occurred.
**/
INTN
TcpInsertTcb (
IN TCP_CB *Tcb
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Head;
TCP_CB *Node;
ASSERT (
(Tcb != NULL) &&
((Tcb->State == TCP_LISTEN) ||
(Tcb->State == TCP_SYN_SENT) ||
(Tcb->State == TCP_SYN_RCVD) ||
(Tcb->State == TCP_CLOSED))
);
if (Tcb->LocalEnd.Port == 0) {
return -1;
}
Head = &mTcpRunQue;
if (Tcb->State == TCP_LISTEN) {
Head = &mTcpListenQue;
}
//
// Check that Tcb isn't already on the list.
//
NET_LIST_FOR_EACH (Entry, Head) {
Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd) &&
TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd)) {
return -1;
}
}
InsertHeadList (Head, &Tcb->List);
return 0;
}
/**
Clone a TCB_CB from Tcb.
@param Tcb Pointer to the TCP_CB to be cloned.
@return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
**/
TCP_CB *
TcpCloneTcb (
IN TCP_CB *Tcb
)
{
TCP_CB *Clone;
Clone = AllocatePool (sizeof (TCP_CB));
if (Clone == NULL) {
return NULL;
}
CopyMem (Clone, Tcb, sizeof (TCP_CB));
//
// Increate the reference count of the shared IpInfo.
//
NET_GET_REF (Tcb->IpInfo);
InitializeListHead (&Clone->List);
InitializeListHead (&Clone->SndQue);
InitializeListHead (&Clone->RcvQue);
Clone->Sk = SockClone (Tcb->Sk);
if (Clone->Sk == NULL) {
DEBUG ((EFI_D_ERROR, "TcpCloneTcb: failed to clone a sock\n"));
FreePool (Clone);
return NULL;
}
((TCP4_PROTO_DATA *) (Clone->Sk->ProtoReserved))->TcpPcb = Clone;
return Clone;
}
/**
Compute an ISS to be used by a new connection.
@return The result ISS.
**/
TCP_SEQNO
TcpGetIss (
VOID
)
{
mTcpGlobalIss += 2048;
return mTcpGlobalIss;
}
/**
Get the local mss.
@param Sock Pointer to the socket to get mss
@return The mss size.
**/
UINT16
TcpGetRcvMss (
IN SOCKET *Sock
)
{
EFI_IP4_MODE_DATA Ip4Mode;
TCP4_PROTO_DATA *TcpProto;
EFI_IP4_PROTOCOL *Ip;
ASSERT (Sock != NULL);
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
Ip = TcpProto->TcpService->IpIo->Ip.Ip4;
ASSERT (Ip != NULL);
Ip->GetModeData (Ip, &Ip4Mode, NULL, NULL);
return (UINT16) (Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD));
}
/**
Set the Tcb's state.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param State The state to be set.
**/
VOID
TcpSetState (
IN OUT TCP_CB *Tcb,
IN UINT8 State
)
{
ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
DEBUG (
(EFI_D_NET,
"Tcb (%p) state %s --> %s\n",
Tcb,
mTcpStateName[Tcb->State],
mTcpStateName[State])
);
Tcb->State = State;
switch (State) {
case TCP_ESTABLISHED:
SockConnEstablished (Tcb->Sk);
if (Tcb->Parent != NULL) {
//
// A new connection is accepted by a listening socket, install
// the device path.
//
TcpInstallDevicePath (Tcb->Sk);
}
break;
case TCP_CLOSED:
SockConnClosed (Tcb->Sk);
break;
default:
break;
}
}
/**
Compute the TCP segment's checksum.
@param Nbuf Pointer to the buffer that contains the TCP
segment.
@param HeadSum The checksum value of the fixed part of pseudo
header.
@return The checksum value.
**/
UINT16
TcpChecksum (
IN NET_BUF *Nbuf,
IN UINT16 HeadSum
)
{
UINT16 Checksum;
Checksum = NetbufChecksum (Nbuf);
Checksum = NetAddChecksum (Checksum, HeadSum);
Checksum = NetAddChecksum (
Checksum,
HTONS ((UINT16) Nbuf->TotalSize)
);
return (UINT16) ~Checksum;
}
/**
Translate the information from the head of the received TCP
segment Nbuf contains and fill it into a TCP_SEG structure.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer contains the TCP segment.
@return Pointer to the TCP_SEG that contains the translated TCP head information.
**/
TCP_SEG *
TcpFormatNetbuf (
IN TCP_CB *Tcb,
IN OUT NET_BUF *Nbuf
)
{
TCP_SEG *Seg;
TCP_HEAD *Head;
Seg = TCPSEG_NETBUF (Nbuf);
Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
ASSERT (Head != NULL);
Nbuf->Tcp = Head;
Seg->Seq = NTOHL (Head->Seq);
Seg->Ack = NTOHL (Head->Ack);
Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2));
Seg->Urg = NTOHS (Head->Urg);
Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale);
Seg->Flag = Head->Flag;
//
// SYN and FIN flag occupy one sequence space each.
//
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
//
// RFC requires that initial window not be scaled
//
Seg->Wnd = NTOHS (Head->Wnd);
Seg->End++;
}
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
Seg->End++;
}
return Seg;
}
/**
Reset the connection related with Tcb.
@param Tcb Pointer to the TCP_CB of the connection to be
reset.
**/
VOID
TcpResetConnection (
IN TCP_CB *Tcb
)
{
NET_BUF *Nbuf;
TCP_HEAD *Nhead;
Nbuf = NetbufAlloc (TCP_MAX_HEAD);
if (Nbuf == NULL) {
return ;
}
Nhead = (TCP_HEAD *) NetbufAllocSpace (
Nbuf,
sizeof (TCP_HEAD),
NET_BUF_TAIL
);
ASSERT (Nhead != NULL);
Nbuf->Tcp = Nhead;
Nhead->Flag = TCP_FLG_RST;
Nhead->Seq = HTONL (Tcb->SndNxt);
Nhead->Ack = HTONL (Tcb->RcvNxt);
Nhead->SrcPort = Tcb->LocalEnd.Port;
Nhead->DstPort = Tcb->RemoteEnd.Port;
Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2);
Nhead->Res = 0;
Nhead->Wnd = HTONS (0xFFFF);
Nhead->Checksum = 0;
Nhead->Urg = 0;
Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip);
NetbufFree (Nbuf);
}
/**
Initialize an active connection.
@param Tcb Pointer to the TCP_CB that wants to initiate a
connection.
**/
VOID
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
)
{
TcpInitTcbLocal (Tcb);
TcpSetState (Tcb, TCP_SYN_SENT);
TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
TcpToSendData (Tcb, 1);
}
/**
Initiate the connection close procedure, called when
applications want to close the connection.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpOnAppClose (
IN OUT TCP_CB *Tcb
)
{
ASSERT (Tcb != NULL);
if (!IsListEmpty (&Tcb->RcvQue) || GET_RCV_DATASIZE (Tcb->Sk) != 0) {
DEBUG ((EFI_D_WARN, "TcpOnAppClose: connection reset "
"because data is lost for TCB %p\n", Tcb));
TcpResetConnection (Tcb);
TcpClose (Tcb);
return;
}
switch (Tcb->State) {
case TCP_CLOSED:
case TCP_LISTEN:
case TCP_SYN_SENT:
TcpSetState (Tcb, TCP_CLOSED);
break;
case TCP_SYN_RCVD:
case TCP_ESTABLISHED:
TcpSetState (Tcb, TCP_FIN_WAIT_1);
break;
case TCP_CLOSE_WAIT:
TcpSetState (Tcb, TCP_LAST_ACK);
break;
default:
break;
}
TcpToSendData (Tcb, 1);
}
/**
Check whether the application's newly delivered data can be sent out.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@retval 0 Whether the data is sent out or is buffered for
further sending.
@retval -1 The Tcb is not in a state that data is permitted to
be sent out.
**/
INTN
TcpOnAppSend (
IN OUT TCP_CB *Tcb
)
{
switch (Tcb->State) {
case TCP_CLOSED:
return -1;
case TCP_LISTEN:
return -1;
case TCP_SYN_SENT:
case TCP_SYN_RCVD:
return 0;
case TCP_ESTABLISHED:
case TCP_CLOSE_WAIT:
TcpToSendData (Tcb, 0);
return 0;
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSING:
case TCP_LAST_ACK:
case TCP_TIME_WAIT:
return -1;
default:
break;
}
return 0;
}
/**
Application has consumed some data, check whether
to send a window updata ack or a delayed ack.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpOnAppConsume (
IN TCP_CB *Tcb
)
{
UINT32 TcpOld;
switch (Tcb->State) {
case TCP_CLOSED:
return;
case TCP_LISTEN:
return;
case TCP_SYN_SENT:
case TCP_SYN_RCVD:
return;
case TCP_ESTABLISHED:
TcpOld = TcpRcvWinOld (Tcb);
if (TcpRcvWinNow (Tcb) > TcpOld) {
if (TcpOld < Tcb->RcvMss) {
DEBUG ((EFI_D_NET, "TcpOnAppConsume: send a window"
" update for a window closed Tcb %p\n", Tcb));
TcpSendAck (Tcb);
} else if (Tcb->DelayedAck == 0) {
DEBUG ((EFI_D_NET, "TcpOnAppConsume: scheduled a delayed"
" ACK to update window for Tcb %p\n", Tcb));
Tcb->DelayedAck = 1;
}
}
break;
case TCP_CLOSE_WAIT:
return;
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSING:
case TCP_LAST_ACK:
case TCP_TIME_WAIT:
return;
default:
break;
}
}
/**
Abort the connection by sending a reset segment, called
when the application wants to abort the connection.
@param Tcb Pointer to the TCP_CB of the TCP instance.
**/
VOID
TcpOnAppAbort (
IN TCP_CB *Tcb
)
{
DEBUG ((EFI_D_WARN, "TcpOnAppAbort: connection reset "
"issued by application for TCB %p\n", Tcb));
switch (Tcb->State) {
case TCP_SYN_RCVD:
case TCP_ESTABLISHED:
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSE_WAIT:
TcpResetConnection (Tcb);
break;
default:
break;
}
TcpSetState (Tcb, TCP_CLOSED);
}
/**
Install the device path protocol on the TCP instance.
@param Sock Pointer to the socket representing the TCP instance.
@retval EFI_SUCCESS The device path protocol is installed.
@retval other Failed to install the device path protocol.
**/
EFI_STATUS
TcpInstallDevicePath (
IN SOCKET *Sock
)
{
TCP4_PROTO_DATA *TcpProto;
TCP4_SERVICE_DATA *TcpService;
TCP_CB *Tcb;
IPv4_DEVICE_PATH Ip4DPathNode;
EFI_STATUS Status;
TCP_PORTNO LocalPort;
TCP_PORTNO RemotePort;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
TcpService = TcpProto->TcpService;
Tcb = TcpProto->TcpPcb;
LocalPort = NTOHS (Tcb->LocalEnd.Port);
RemotePort = NTOHS (Tcb->RemoteEnd.Port);
NetLibCreateIPv4DPathNode (
&Ip4DPathNode,
TcpService->ControllerHandle,
Tcb->LocalEnd.Ip,
LocalPort,
Tcb->RemoteEnd.Ip,
RemotePort,
EFI_IP_PROTO_TCP,
Tcb->UseDefaultAddr
);
IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask);
Sock->DevicePath = AppendDevicePathNode (
Sock->ParentDevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) &Ip4DPathNode
);
if (Sock->DevicePath == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gBS->InstallProtocolInterface (
&Sock->SockHandle,
&gEfiDevicePathProtocolGuid,
EFI_NATIVE_INTERFACE,
Sock->DevicePath
);
if (EFI_ERROR (Status)) {
FreePool (Sock->DevicePath);
}
return Status;
}

View File

@ -1,352 +0,0 @@
/** @file
Routines to process TCP option.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
/**
Get a UINT16 value from buffer.
@param Buf Pointer to input buffer.
@return The UINT16 value get from buffer.
**/
UINT16
TcpGetUint16 (
IN UINT8 *Buf
)
{
UINT16 Value;
CopyMem (&Value, Buf, sizeof (UINT16));
return NTOHS (Value);
}
/**
Get a UINT32 value from buffer.
@param Buf Pointer to input buffer.
@return The UINT32 value get from buffer.
**/
UINT32
TcpGetUint32 (
IN UINT8 *Buf
)
{
UINT32 Value;
CopyMem (&Value, Buf, sizeof (UINT32));
return NTOHL (Value);
}
/**
Put a UINT32 value in buffer.
@param Buf Pointer to the buffer.
@param Data The UINT32 Date to put in buffer
**/
VOID
TcpPutUint32 (
OUT UINT8 *Buf,
IN UINT32 Data
)
{
Data = HTONL (Data);
CopyMem (Buf, &Data, sizeof (UINT32));
}
/**
Compute the window scale value according to the given buffer size.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return The scale value.
**/
UINT8
TcpComputeScale (
IN TCP_CB *Tcb
)
{
UINT8 Scale;
UINT32 BufSize;
ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
Scale = 0;
while ((Scale < TCP_OPTION_MAX_WS) &&
((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
Scale++;
}
return Scale;
}
/**
Build the TCP option in three-way handshake.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpSynBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
)
{
UINT8 *Data;
UINT16 Len;
ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
Len = 0;
//
// Add timestamp option if not disabled by application
// and it is the first SYN segment or the peer has sent
// us its timestamp.
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_TS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data != NULL);
Len += TCP_OPTION_TS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
TcpPutUint32 (Data + 4, mTcpTick);
TcpPutUint32 (Data + 8, 0);
}
//
// Build window scale option, only when are configured
// to send WS option, and either we are doing active
// open or we have received WS option from peer.
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_WS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data != NULL);
Len += TCP_OPTION_WS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
}
//
// Build MSS option
//
Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
ASSERT (Data != NULL);
Len += TCP_OPTION_MSS_LEN;
TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
return Len;
}
/**
Build the TCP option in synchronized states.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
)
{
UINT8 *Data;
UINT16 Len;
ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
Len = 0;
//
// Build Timestamp option
//
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_TS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data != NULL);
Len += TCP_OPTION_TS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
TcpPutUint32 (Data + 4, mTcpTick);
TcpPutUint32 (Data + 8, Tcb->TsRecent);
}
return Len;
}
/**
Parse the supported options.
@param Tcp Pointer to the TCP_CB of this TCP instance.
@param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
options.
@retval 0 The options are successfully pasrsed.
@retval -1 Ilegal option was found.
**/
INTN
TcpParseOption (
IN TCP_HEAD *Tcp,
IN OUT TCP_OPTION *Option
)
{
UINT8 *Head;
UINT8 TotalLen;
UINT8 Cur;
UINT8 Type;
UINT8 Len;
ASSERT ((Tcp != NULL) && (Option != NULL));
Option->Flag = 0;
TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
if (TotalLen <= 0) {
return 0;
}
Head = (UINT8 *) (Tcp + 1);
//
// Fast process of timestamp option
//
if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
(TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
Option->TSVal = TcpGetUint32 (Head + 4);
Option->TSEcr = TcpGetUint32 (Head + 8);
Option->Flag = TCP_OPTION_RCVD_TS;
return 0;
}
//
// Slow path to process the options.
//
Cur = 0;
while (Cur < TotalLen) {
Type = Head[Cur];
switch (Type) {
case TCP_OPTION_MSS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_MSS_LEN) ||
(TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
return -1;
}
Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
Cur += TCP_OPTION_MSS_LEN;
break;
case TCP_OPTION_WS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_WS_LEN) ||
(TotalLen - Cur < TCP_OPTION_WS_LEN)) {
return -1;
}
Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
Cur += TCP_OPTION_WS_LEN;
break;
case TCP_OPTION_TS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_TS_LEN) ||
(TotalLen - Cur < TCP_OPTION_TS_LEN)) {
return -1;
}
Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
Cur += TCP_OPTION_TS_LEN;
break;
case TCP_OPTION_NOP:
Cur++;
break;
case TCP_OPTION_EOP:
Cur = TotalLen;
break;
default:
Len = Head[Cur + 1];
if ((TotalLen - Cur) < Len || Len < 2) {
return -1;
}
Cur = (UINT8) (Cur + Len);
break;
}
}
return 0;
}

View File

@ -1,130 +0,0 @@
/** @file
Tcp option's routine header file.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TCP4_OPTION_H_
#define _TCP4_OPTION_H_
///
/// The structure to store the parse option value.
/// ParseOption only parse the options, don't process them.
///
typedef struct _TCP_OPTION {
UINT8 Flag; ///< Flag such as TCP_OPTION_RCVD_MSS
UINT8 WndScale; ///< The WndScale received
UINT16 Mss; ///< The Mss received
UINT32 TSVal; ///< The TSVal field in a timestamp option
UINT32 TSEcr; ///< The TSEcr field in a timestamp option
} TCP_OPTION;
//
// supported TCP option type and their length
//
#define TCP_OPTION_EOP 0 ///< End Of oPtion
#define TCP_OPTION_NOP 1 ///< No-Option.
#define TCP_OPTION_MSS 2 ///< Maximum Segment Size
#define TCP_OPTION_WS 3 ///< Window scale
#define TCP_OPTION_TS 8 ///< Timestamp
#define TCP_OPTION_MSS_LEN 4 ///< Length of MSS option
#define TCP_OPTION_WS_LEN 3 ///< Length of window scale option
#define TCP_OPTION_TS_LEN 10 ///< Length of timestamp option
#define TCP_OPTION_WS_ALIGNED_LEN 4 ///< Length of window scale option, aligned
#define TCP_OPTION_TS_ALIGNED_LEN 12 ///< Length of timestamp option, aligned
//
// recommend format of timestamp window scale
// option for fast process.
//
#define TCP_OPTION_TS_FAST ((TCP_OPTION_NOP << 24) | \
(TCP_OPTION_NOP << 16) | \
(TCP_OPTION_TS << 8) | \
(TCP_OPTION_TS_LEN))
#define TCP_OPTION_WS_FAST ((TCP_OPTION_NOP << 24) | \
(TCP_OPTION_WS << 16) | \
(TCP_OPTION_WS_LEN << 8))
#define TCP_OPTION_MSS_FAST ((TCP_OPTION_MSS << 24) | (TCP_OPTION_MSS_LEN << 16))
//
// Other misc definations
//
#define TCP_OPTION_RCVD_MSS 0x01
#define TCP_OPTION_RCVD_WS 0x02
#define TCP_OPTION_RCVD_TS 0x04
#define TCP_OPTION_MAX_WS 14 ///< Maxium window scale value
#define TCP_OPTION_MAX_WIN 0xffff ///< Max window size in TCP header
/**
Compute the window scale value according to the given buffer size.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return The scale value.
**/
UINT8
TcpComputeScale (
IN TCP_CB *Tcb
);
/**
Build the TCP option in three-way handshake.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpSynBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
/**
Build the TCP option in synchronized states.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
/**
Parse the supported options.
@param Tcp Pointer to the TCP_CB of this TCP instance.
@param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
options.
@retval 0 The options are successfully pasrsed.
@retval -1 Ilegal option was found.
**/
INTN
TcpParseOption (
IN TCP_HEAD *Tcp,
IN OUT TCP_OPTION *Option
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,357 +0,0 @@
/** @file
Tcp Protocol header file.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TCP4_PROTO_H_
#define _TCP4_PROTO_H_
typedef struct _TCP_CB TCP_CB;
#include "Tcp4Driver.h"
#include "Socket.h"
#include "Tcp4Option.h"
///
/// Tcp states, Don't change their order, it is used as
/// index to mTcpOutFlag and other macros
///
#define TCP_CLOSED 0
#define TCP_LISTEN 1
#define TCP_SYN_SENT 2
#define TCP_SYN_RCVD 3
#define TCP_ESTABLISHED 4
#define TCP_FIN_WAIT_1 5
#define TCP_FIN_WAIT_2 6
#define TCP_CLOSING 7
#define TCP_TIME_WAIT 8
#define TCP_CLOSE_WAIT 9
#define TCP_LAST_ACK 10
///
/// Flags in the TCP header
///
#define TCP_FLG_FIN 0x01
#define TCP_FLG_SYN 0x02
#define TCP_FLG_RST 0x04
#define TCP_FLG_PSH 0x08
#define TCP_FLG_ACK 0x10
#define TCP_FLG_URG 0x20
//
// mask for all the flags
//
#define TCP_FLG_FLAG 0x3F
#define TCP_CONNECT_REFUSED (-1) ///< TCP error status
#define TCP_CONNECT_RESET (-2) ///< TCP error status
#define TCP_CONNECT_CLOSED (-3) ///< TCP error status
//
// Current congestion status as suggested by RFC3782.
//
#define TCP_CONGEST_RECOVER 1 ///< During the NewReno fast recovery
#define TCP_CONGEST_LOSS 2 ///< Retxmit because of retxmit time out
#define TCP_CONGEST_OPEN 3 ///< TCP is opening its congestion window
//
// TCP control flags
//
#define TCP_CTRL_NO_NAGLE 0x0001 ///< Disable Nagle algorithm
#define TCP_CTRL_NO_KEEPALIVE 0x0002 ///< Disable keepalive timer
#define TCP_CTRL_NO_WS 0x0004 ///< Disable window scale option
#define TCP_CTRL_RCVD_WS 0x0008 ///< Received a wnd scale option in syn
#define TCP_CTRL_NO_TS 0x0010 ///< Disable Timestamp option
#define TCP_CTRL_RCVD_TS 0x0020 ///< Received a Timestamp option in syn
#define TCP_CTRL_SND_TS 0x0040 ///< Send Timestamp option to remote
#define TCP_CTRL_SND_URG 0x0080 ///< In urgent send mode
#define TCP_CTRL_RCVD_URG 0x0100 ///< In urgent receive mode
#define TCP_CTRL_SND_PSH 0x0200 ///< In PUSH send mode
#define TCP_CTRL_FIN_SENT 0x0400 ///< FIN is sent
#define TCP_CTRL_FIN_ACKED 0x0800 ///< FIN is ACKed.
#define TCP_CTRL_TIMER_ON 0x1000 ///< At least one of the timer is on
#define TCP_CTRL_RTT_ON 0x2000 ///< The RTT measurement is on
#define TCP_CTRL_ACK_NOW 0x4000 ///< Send the ACK now, don't delay
//
// Timer related values
//
#define TCP_TIMER_CONNECT 0 ///< Connection establishment timer
#define TCP_TIMER_REXMIT 1 ///< Retransmit timer
#define TCP_TIMER_PROBE 2 ///< Window probe timer
#define TCP_TIMER_KEEPALIVE 3 ///< Keepalive timer
#define TCP_TIMER_FINWAIT2 4 ///< FIN_WAIT_2 timer
#define TCP_TIMER_2MSL 5 ///< TIME_WAIT tiemr
#define TCP_TIMER_NUMBER 6 ///< The total number of TCP timer.
#define TCP_TICK 200 ///< Every TCP tick is 200ms
#define TCP_TICK_HZ 5 ///< The frequence of TCP tick
#define TCP_RTT_SHIFT 3 ///< SRTT & RTTVAR scaled by 8
#define TCP_RTO_MIN TCP_TICK_HZ ///< The minium value of RTO
#define TCP_RTO_MAX (TCP_TICK_HZ * 60) ///< The maxium value of RTO
#define TCP_FOLD_RTT 4 ///< Timeout threshod to fold RTT
//
// Default values for some timers
//
#define TCP_MAX_LOSS 12 ///< Default max times to retxmit
#define TCP_KEEPALIVE_IDLE_MIN (TCP_TICK_HZ * 60 * 60 * 2) ///< First keep alive
#define TCP_KEEPALIVE_PERIOD (TCP_TICK_HZ * 60)
#define TCP_MAX_KEEPALIVE 8
#define TCP_FIN_WAIT2_TIME (2 * TCP_TICK_HZ)
#define TCP_TIME_WAIT_TIME (2 * TCP_TICK_HZ)
#define TCP_PAWS_24DAY (24 * 24 * 60 * 60 * TCP_TICK_HZ)
#define TCP_CONNECT_TIME (75 * TCP_TICK_HZ)
//
// The header space to be reserved before TCP data to accomodate :
// 60byte IP head + 60byte TCP head + link layer head
//
#define TCP_MAX_HEAD 192
//
// Value ranges for some control option
//
#define TCP_RCV_BUF_SIZE (2 * 1024 * 1024)
#define TCP_RCV_BUF_SIZE_MIN (8 * 1024)
#define TCP_SND_BUF_SIZE (2 * 1024 * 1024)
#define TCP_SND_BUF_SIZE_MIN (8 * 1024)
#define TCP_BACKLOG 10
#define TCP_BACKLOG_MIN 5
#define TCP_MAX_LOSS_MIN 6
#define TCP_CONNECT_TIME_MIN (60 * TCP_TICK_HZ)
#define TCP_MAX_KEEPALIVE_MIN 4
#define TCP_KEEPALIVE_IDLE_MAX (TCP_TICK_HZ * 60 * 60 * 4)
#define TCP_KEEPALIVE_PERIOD_MIN (TCP_TICK_HZ * 30)
#define TCP_FIN_WAIT2_TIME_MAX (4 * TCP_TICK_HZ)
#define TCP_TIME_WAIT_TIME_MAX (60 * TCP_TICK_HZ)
///
/// TCP segmentation data
///
typedef struct _TCP_SEG {
TCP_SEQNO Seq; ///< Starting sequence number
TCP_SEQNO End; ///< The sequence of the last byte + 1, include SYN/FIN. End-Seq = SEG.LEN
TCP_SEQNO Ack; ///< ACK field in the segment
UINT8 Flag; ///< TCP header flags
UINT16 Urg; ///< Valid if URG flag is set.
UINT32 Wnd; ///< TCP window size field
} TCP_SEG;
///
/// Network endpoint, IP+Port structure
///
typedef struct _TCP_PEER {
UINT32 Ip; ///< IP address, network byte order
TCP_PORTNO Port; ///< Port number, network byte order
} TCP_PEER;
///
/// TCP control block, it includes various states
///
struct _TCP_CB {
LIST_ENTRY List; ///< Back and forward link entry
TCP_CB *Parent; ///< The parent TCP_CB structure
SOCKET *Sk; ///< The socket it controled.
TCP_PEER LocalEnd; ///< Local endpoint
TCP_PEER RemoteEnd;///< Remote endpoint
LIST_ENTRY SndQue; ///< Retxmission queue
LIST_ENTRY RcvQue; ///< Reassemble queue
UINT32 CtrlFlag; ///< Control flags, such as NO_NAGLE
INT32 Error; ///< Soft error status, such as TCP_CONNECT_RESET
//
// RFC793 and RFC1122 defined variables
//
UINT8 State; ///< TCP state, such as SYN_SENT, LISTEN
UINT8 DelayedAck; ///< Number of delayed ACKs
UINT16 HeadSum; ///< Checksum of the fixed parts of pesudo
///< header: Src IP, Dst IP, 0, Protocol,
///< not include the TCP length.
TCP_SEQNO Iss; ///< Initial Sending Sequence
TCP_SEQNO SndUna; ///< First unacknowledged data
TCP_SEQNO SndNxt; ///< Next data sequence to send.
TCP_SEQNO SndPsh; ///< Send PUSH point
TCP_SEQNO SndUp; ///< Send urgent point
UINT32 SndWnd; ///< Window advertised by the remote peer
UINT32 SndWndMax; ///< Max send window advertised by the peer
TCP_SEQNO SndWl1; ///< Seq number used for last window update
TCP_SEQNO SndWl2; ///< Ack no of last window update
UINT16 SndMss; ///< Max send segment size
TCP_SEQNO RcvNxt; ///< Next sequence no to receive
UINT32 RcvWnd; ///< Window advertised by the local peer
TCP_SEQNO RcvWl2; ///< The RcvNxt (or ACK) of last window update.
///< It is necessary because of delayed ACK
TCP_SEQNO RcvUp; ///< Urgent point;
TCP_SEQNO Irs; ///< Initial Receiving Sequence
UINT16 RcvMss; ///< Max receive segment size
UINT16 EnabledTimer; ///< Which timer is currently enabled
UINT32 Timer[TCP_TIMER_NUMBER]; ///< When the timer will expire
INT32 NextExpire; ///< Count down offset for the nearest timer
UINT32 Idle; ///< How long the connection is in idle
UINT32 ProbeTime; ///< The time out value for current window prober
BOOLEAN ProbeTimerOn;///< If TRUE, the probe time is on.
//
// RFC1323 defined variables, about window scale,
// timestamp and PAWS
//
UINT8 SndWndScale; ///< Wndscale received from the peer
UINT8 RcvWndScale; ///< Wndscale used to scale local buffer
UINT32 TsRecent; ///< TsRecent to echo to the remote peer
UINT32 TsRecentAge; ///< When this TsRecent is updated
//
// RFC2988 defined variables. about RTT measurement
//
TCP_SEQNO RttSeq; ///< The seq of measured segment now
UINT32 RttMeasure; ///< Currently measured RTT in heart beats
UINT32 SRtt; ///< Smoothed RTT, scaled by 8
UINT32 RttVar; ///< RTT variance, scaled by 8
UINT32 Rto; ///< Current RTO, not scaled
//
// RFC2581, and 3782 variables.
// Congestion control + NewReno fast recovery.
//
UINT32 CWnd; ///< Sender's congestion window
UINT32 Ssthresh; ///< Slow start threshold.
TCP_SEQNO Recover; ///< Recover point for NewReno
UINT16 DupAck; ///< Number of duplicate ACKs
UINT8 CongestState; ///< The current congestion state(RFC3782)
UINT8 LossTimes; ///< Number of retxmit timeouts in a row
TCP_SEQNO LossRecover; ///< Recover point for retxmit
//
// configuration parameters, for EFI_TCP4_PROTOCOL specification
//
UINT32 KeepAliveIdle; ///< Idle time before sending first probe
UINT32 KeepAlivePeriod; ///< Interval for subsequent keep alive probe
UINT8 MaxKeepAlive; ///< Maxium keep alive probe times.
UINT8 KeepAliveProbes; ///< The number of keep alive probe.
UINT16 MaxRexmit; ///< The maxium number of retxmit before abort
UINT32 FinWait2Timeout; ///< The FIN_WAIT_2 time out
UINT32 TimeWaitTimeout; ///< The TIME_WAIT time out
UINT32 ConnectTimeout; ///< The connect establishment time out
//
// RFC7323
// Addressing Window Retraction for TCP Window Scale Option.
//
TCP_SEQNO RetxmitSeqMax; ///< Max Seq number in previous retransmission.
//
// configuration for tcp provided by user
//
BOOLEAN UseDefaultAddr;
UINT8 Tos;
UINT8 Ttl;
EFI_IPv4_ADDRESS SubnetMask;
IP_IO_IP_INFO *IpInfo; ///<pointer reference to Ip used to send pkt
};
extern LIST_ENTRY mTcpRunQue;
extern LIST_ENTRY mTcpListenQue;
extern TCP_SEQNO mTcpGlobalIss;
extern UINT32 mTcpTick;
///
/// TCP_CONNECTED: both ends have synchronized their ISN.
///
#define TCP_CONNECTED(state) ((state) > TCP_SYN_RCVD)
#define TCP_FIN_RCVD(State) \
(((State) == TCP_CLOSE_WAIT) || \
((State) == TCP_LAST_ACK) || \
((State) == TCP_CLOSING) || \
((State) == TCP_TIME_WAIT))
#define TCP_LOCAL_CLOSED(State) \
(((State) == TCP_FIN_WAIT_1) || \
((State) == TCP_FIN_WAIT_2) || \
((State) == TCP_CLOSING) || \
((State) == TCP_TIME_WAIT) || \
((State) == TCP_LAST_ACK))
//
// Get the TCP_SEG point from a net buffer's ProtoData
//
#define TCPSEG_NETBUF(NBuf) ((TCP_SEG *) ((NBuf)->ProtoData))
//
// macros to compare sequence no
//
#define TCP_SEQ_LT(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) < 0)
#define TCP_SEQ_LEQ(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) <= 0)
#define TCP_SEQ_GT(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) < 0)
#define TCP_SEQ_GEQ(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) <= 0)
//
// TCP_SEQ_BETWEEN return whether b <= m <= e
//
#define TCP_SEQ_BETWEEN(b, m, e) ((e) - (b) >= (m) - (b))
//
// TCP_SUB_SEQ returns Seq1 - Seq2. Make sure Seq1 >= Seq2
//
#define TCP_SUB_SEQ(Seq1, Seq2) ((UINT32) ((Seq1) - (Seq2)))
//
// Check whether Flag is on
//
#define TCP_FLG_ON(Value, Flag) ((BOOLEAN) (((Value) & (Flag)) != 0))
//
// Set and Clear operation on a Flag
//
#define TCP_SET_FLG(Value, Flag) ((Value) |= (Flag))
#define TCP_CLEAR_FLG(Value, Flag) ((Value) &= ~(Flag))
//
// Test whether two peers are equal
//
#define TCP_PEER_EQUAL(Pa, Pb) \
(((Pa)->Ip == (Pb)->Ip) && ((Pa)->Port == (Pb)->Port))
//
// Test whether Pa matches Pb, or Pa is more specific
// than pb. Zero means wildcard.
//
#define TCP_PEER_MATCH(Pa, Pb) \
((((Pb)->Ip == 0) || ((Pb)->Ip == (Pa)->Ip)) && \
(((Pb)->Port == 0) || ((Pb)->Port == (Pa)->Port)))
#define TCP_TIMER_ON(Flag, Timer) ((Flag) & (1 << (Timer)))
#define TCP_SET_TIMER(Flag, Timer) ((Flag) = (UINT16) ((Flag) | (1 << (Timer))))
#define TCP_CLEAR_TIMER(Flag, Timer) ((Flag) = (UINT16) ((Flag) & (~(1 << (Timer)))))
#define TCP_TIME_LT(Ta, Tb) ((INT32) ((Ta) - (Tb)) < 0)
#define TCP_TIME_LEQ(Ta, Tb) ((INT32) ((Ta) - (Tb)) <= 0)
#define TCP_SUB_TIME(Ta, Tb) ((UINT32) ((Ta) - (Tb)))
#define TCP_MAX_WIN 0xFFFFU
typedef
VOID
(*TCP_TIMER_HANDLER) (
IN OUT TCP_CB *Tcb
);
#endif

View File

@ -1,584 +0,0 @@
/** @file
TCP timer related functions.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php<BR>
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Tcp4Main.h"
UINT32 mTcpTick = 1000;
/**
Connect timeout handler.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpConnectTimeout (
IN OUT TCP_CB *Tcb
);
/**
Timeout handler for TCP retransmission timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpRexmitTimeout (
IN OUT TCP_CB *Tcb
);
/**
Timeout handler for window probe timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpProbeTimeout (
IN OUT TCP_CB *Tcb
);
/**
Timeout handler for keepalive timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpKeepaliveTimeout (
IN OUT TCP_CB *Tcb
);
/**
Timeout handler for FIN_WAIT_2 timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpFinwait2Timeout (
IN OUT TCP_CB *Tcb
);
/**
Timeout handler for 2MSL timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
Tcp2MSLTimeout (
IN OUT TCP_CB *Tcb
);
TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
TcpConnectTimeout,
TcpRexmitTimeout,
TcpProbeTimeout,
TcpKeepaliveTimeout,
TcpFinwait2Timeout,
Tcp2MSLTimeout,
};
/**
Close the TCP connection.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpClose (
IN OUT TCP_CB *Tcb
)
{
NetbufFreeList (&Tcb->SndQue);
NetbufFreeList (&Tcb->RcvQue);
TcpSetState (Tcb, TCP_CLOSED);
}
/**
Connect timeout handler.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpConnectTimeout (
IN OUT TCP_CB *Tcb
)
{
if (!TCP_CONNECTED (Tcb->State)) {
DEBUG ((EFI_D_ERROR, "TcpConnectTimeout: connection closed "
"because conenction timer timeout for TCB %p\n", Tcb));
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
if (TCP_SYN_RCVD == Tcb->State) {
DEBUG ((EFI_D_WARN, "TcpConnectTimeout: send reset because "
"connection timer timeout for TCB %p\n", Tcb));
TcpResetConnection (Tcb);
}
TcpClose (Tcb);
}
}
/**
Timeout handler for TCP retransmission timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpRexmitTimeout (
IN OUT TCP_CB *Tcb
)
{
UINT32 FlightSize;
DEBUG ((EFI_D_WARN, "TcpRexmitTimeout: transmission "
"timeout for TCB %p\n", Tcb));
//
// Set the congestion window. FlightSize is the
// amount of data that has been sent but not
// yet ACKed.
//
FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
Tcb->Ssthresh = MAX ((UINT32) (2 * Tcb->SndMss), FlightSize / 2);
Tcb->CWnd = Tcb->SndMss;
Tcb->LossRecover = Tcb->SndNxt;
Tcb->LossTimes++;
if ((Tcb->LossTimes > Tcb->MaxRexmit) &&
!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {
DEBUG ((EFI_D_ERROR, "TcpRexmitTimeout: connection closed "
"because too many timeouts for TCB %p\n", Tcb));
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
TcpClose (Tcb);
return ;
}
TcpBackoffRto (Tcb);
TcpRetransmit (Tcb, Tcb->SndUna);
TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
Tcb->CongestState = TCP_CONGEST_LOSS;
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
}
/**
Timeout handler for window probe timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpProbeTimeout (
IN OUT TCP_CB *Tcb
)
{
//
// This is the timer for sender's SWSA. RFC1122 requires
// a timer set for sender's SWSA, and suggest combine it
// with window probe timer. If data is sent, don't set
// the probe timer, since retransmit timer is on.
//
if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {
ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT) != 0);
Tcb->ProbeTimerOn = FALSE;
return ;
}
TcpSendZeroProbe (Tcb);
TcpSetProbeTimer (Tcb);
}
/**
Timeout handler for keepalive timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpKeepaliveTimeout (
IN OUT TCP_CB *Tcb
)
{
Tcb->KeepAliveProbes++;
//
// Too many Keep-alive probes, drop the connection
//
if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
TcpClose (Tcb);
return ;
}
TcpSendZeroProbe (Tcb);
TcpSetKeepaliveTimer (Tcb);
}
/**
Timeout handler for FIN_WAIT_2 timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpFinwait2Timeout (
IN OUT TCP_CB *Tcb
)
{
DEBUG ((EFI_D_WARN, "TcpFinwait2Timeout: connection closed "
"because FIN_WAIT2 timer timeouts for TCB %p\n", Tcb));
TcpClose (Tcb);
}
/**
Timeout handler for 2MSL timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
Tcp2MSLTimeout (
IN OUT TCP_CB *Tcb
)
{
DEBUG ((EFI_D_WARN, "Tcp2MSLTimeout: connection closed "
"because TIME_WAIT timer timeouts for TCB %p\n", Tcb));
TcpClose (Tcb);
}
/**
Update the timer status and the next expire time according to the timers
to expire in a specific future time slot.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpUpdateTimer (
IN OUT TCP_CB *Tcb
)
{
UINT16 Index;
//
// Don't use a too large value to init NextExpire
// since mTcpTick wraps around as sequence no does.
//
Tcb->NextExpire = 65535;
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)) {
Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
}
}
}
/**
Enable a TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be enabled.
@param TimeOut The timeout value of this timer.
**/
VOID
TcpSetTimer (
IN OUT TCP_CB *Tcb,
IN UINT16 Timer,
IN UINT32 TimeOut
)
{
TCP_SET_TIMER (Tcb->EnabledTimer, Timer);
Tcb->Timer[Timer] = mTcpTick + TimeOut;
TcpUpdateTimer (Tcb);
}
/**
Clear one TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be cleared.
**/
VOID
TcpClearTimer (
IN OUT TCP_CB *Tcb,
IN UINT16 Timer
)
{
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
TcpUpdateTimer (Tcb);
}
/**
Clear all TCP timers.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpClearAllTimer (
IN OUT TCP_CB *Tcb
)
{
Tcb->EnabledTimer = 0;
TcpUpdateTimer (Tcb);
}
/**
Enable the window prober timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpSetProbeTimer (
IN OUT TCP_CB *Tcb
)
{
if (!Tcb->ProbeTimerOn) {
Tcb->ProbeTime = Tcb->Rto;
Tcb->ProbeTimerOn = TRUE;
} else {
Tcb->ProbeTime <<= 1;
}
if (Tcb->ProbeTime < TCP_RTO_MIN) {
Tcb->ProbeTime = TCP_RTO_MIN;
} else if (Tcb->ProbeTime > TCP_RTO_MAX) {
Tcb->ProbeTime = TCP_RTO_MAX;
}
TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);
}
/**
Enable the keepalive timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpSetKeepaliveTimer (
IN OUT TCP_CB *Tcb
)
{
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {
return ;
}
//
// Set the timer to KeepAliveIdle if either
// 1. the keepalive timer is off
// 2. The keepalive timer is on, but the idle
// is less than KeepAliveIdle, that means the
// connection is alive since our last probe.
//
if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||
(Tcb->Idle < Tcb->KeepAliveIdle)) {
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);
Tcb->KeepAliveProbes = 0;
} else {
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);
}
}
/**
Backoff the RTO.
@param Tcb Pointer to the TCP_CB of this TCP instance.
**/
VOID
TcpBackoffRto (
IN OUT TCP_CB *Tcb
)
{
//
// Fold the RTT estimate if too many times, the estimate
// may be wrong, fold it. So the next time a valid
// measurement is sampled, we can start fresh.
//
if ((Tcb->LossTimes >= TCP_FOLD_RTT) && (Tcb->SRtt != 0)) {
Tcb->RttVar += Tcb->SRtt >> 2;
Tcb->SRtt = 0;
}
Tcb->Rto <<= 1;
if (Tcb->Rto < TCP_RTO_MIN) {
Tcb->Rto = TCP_RTO_MIN;
} else if (Tcb->Rto > TCP_RTO_MAX) {
Tcb->Rto = TCP_RTO_MAX;
}
}
/**
Heart beat timer handler.
@param Context Context of the timer event, ignored.
**/
VOID
EFIAPI
TcpTickingDpc (
IN VOID *Context
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
TCP_CB *Tcb;
INT16 Index;
mTcpTick++;
mTcpGlobalIss += 100;
//
// Don't use LIST_FOR_EACH, which isn't delete safe.
//
for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {
Next = Entry->ForwardLink;
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (Tcb->State == TCP_CLOSED) {
continue;
}
//
// The connection is doing RTT measurement.
//
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
Tcb->RttMeasure++;
}
Tcb->Idle++;
if (Tcb->DelayedAck != 0) {
TcpSendAck (Tcb);
}
//
// No timer is active or no timer expired
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) ||
((--Tcb->NextExpire) > 0)) {
continue;
}
//
// Call the timeout handler for each expired timer.
//
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {
//
// disable the timer before calling the handler
// in case the handler enables it again.
//
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);
mTcpTimerHandler[Index](Tcb);
//
// The Tcb may have been deleted by the timer, or
// no other timer is set.
//
if ((Next->BackLink != Entry) ||
(Tcb->EnabledTimer == 0)) {
break;
}
}
}
//
// If the Tcb still exist or some timer is set, update the timer
//
if (Index == TCP_TIMER_NUMBER) {
TcpUpdateTimer (Tcb);
}
}
}
/**
Heart beat timer handler, queues the DPC at TPL_CALLBACK.
@param Event Timer event signaled, ignored.
@param Context Context of the timer event, ignored.
**/
VOID
EFIAPI
TcpTicking (
IN EFI_EVENT Event,
IN VOID *Context
)
{
QueueDpc (TPL_CALLBACK, TcpTickingDpc, Context);
}