summaryrefslogtreecommitdiff
path: root/StdLib/EfiSocketLib/Tcp4.c
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/EfiSocketLib/Tcp4.c')
-rw-r--r--StdLib/EfiSocketLib/Tcp4.c2432
1 files changed, 0 insertions, 2432 deletions
diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c
deleted file mode 100644
index 68477fba6e..0000000000
--- a/StdLib/EfiSocketLib/Tcp4.c
+++ /dev/null
@@ -1,2432 +0,0 @@
-/** @file
- Implement the TCP4 driver support for the socket layer.
-
- Copyright (c) 2011 - 2015, 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.
-
-
- \section ConnectionManagement Connection Management
-
- The ::EslTcp4Listen routine initially places the SOCK_STREAM or
- SOCK_SEQPACKET socket into a listen state. When a remote machine
- makes a connection to the socket, the TCPv4 network layer calls
- ::EslTcp4ListenComplete to complete the connection processing.
- EslTcp4ListenComplete manages the connections by placing them in
- FIFO order in a queue to be serviced by the application. When the
- number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth),
- the new connection is closed. Eventually, the application indirectly
- calls ::EslTcp4Accept to remove the next connection from the queue
- and get the associated socket.
-
-**/
-
-#include "Socket.h"
-
-
-/**
- Attempt to connect to a remote TCP port
-
- This routine starts the connection processing for a SOCK_STREAM
- or SOCK_SEQPAKCET socket using the TCPv4 network layer. It
- configures the local TCPv4 connection point and then attempts to
- connect to a remote system. Upon completion, the
- ::EslTcp4ConnectComplete routine gets called with the connection
- status.
-
- This routine is called by ::EslSocketConnect to initiate the TCPv4
- network specific connect operations. The connection processing is
- initiated by this routine and finished by ::EslTcp4ConnectComplete.
- This pair of routines walks through the list of local TCPv4
- connection points until a connection to the remote system is
- made.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS The connection was successfully established.
- @retval EFI_NOT_READY The connection is in progress, call this routine again.
- @retval Others The connection attempt failed.
-
- **/
-EFI_STATUS
-EslTcp4ConnectStart (
- IN ESL_SOCKET * pSocket
- );
-
-
-/**
- Process the connection attempt
-
- A system has initiated a connection attempt with a socket in the
- listen state. Attempt to complete the connection.
-
- The TCPv4 layer calls this routine when a connection is made to
- the socket in the listen state. See the
- \ref ConnectionManagement section.
-
- @param [in] Event The listen completion event
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
-**/
-VOID
-EslTcp4ListenComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- );
-
-
-/**
- Accept a network connection.
-
- This routine waits for a network connection to the socket and
- returns the remote network address to the caller if requested.
-
- This routine is called by ::EslSocketAccept to handle the TCPv4 protocol
- specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets.
- See the \ref ConnectionManagement section.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @param [in] pSockAddr Address of a buffer to receive the remote
- network address.
-
- @param [in, out] pSockAddrLength Length in bytes of the address buffer.
- On output specifies the length of the
- remote network address.
-
- @retval EFI_SUCCESS Remote address is available
- @retval Others Remote address not available
-
- **/
-EFI_STATUS
-EslTcp4Accept (
- IN ESL_SOCKET * pSocket,
- IN struct sockaddr * pSockAddr,
- IN OUT socklen_t * pSockAddrLength
- )
-{
- ESL_PORT * pPort;
- struct sockaddr_in * pRemoteAddress;
- ESL_TCP4_CONTEXT * pTcp4;
- UINT32 RemoteAddress;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Validate the socket length
- //
- pRemoteAddress = (struct sockaddr_in *) pSockAddr;
- if (( NULL == pSockAddrLength )
- || ( sizeof ( *pRemoteAddress ) > *pSockAddrLength )) {
- //
- // Invalid socket address
- //
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- DEBUG (( DEBUG_ACCEPT,
- "ERROR - Invalid address length\r\n" ));
- }
- else {
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Locate the address context
- //
- pPort = pSocket->pPortList;
- pTcp4 = &pPort->Context.Tcp4;
-
- //
- // Fill-in the remote address structure
- //
- ZeroMem ( pRemoteAddress, sizeof ( *pRemoteAddress ));
- pRemoteAddress->sin_len = sizeof ( *pRemoteAddress );
- pRemoteAddress->sin_family = AF_INET;
- pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
- RemoteAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];
- RemoteAddress <<= 8;
- RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];
- RemoteAddress <<= 8;
- RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];
- RemoteAddress <<= 8;
- RemoteAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];
- pRemoteAddress->sin_addr.s_addr = RemoteAddress;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Process the remote connection completion event.
-
- This routine handles the completion of a connection attempt. It
- releases the port (TCPv4 adapter connection) in the case of an
- error and start a connection attempt on the next port. If the
- connection attempt was successful then this routine releases all
- of the other ports.
-
- This routine is called by the TCPv4 layer when a connect request
- completes. It sets the ESL_SOCKET::bConnected flag to notify the
- ::EslTcp4ConnectComplete routine that the connection is available.
- The flag is set when the connection is established or no more ports
- exist in the list. The connection status is passed via
- ESL_SOCKET::ConnectStatus.
-
- @param [in] Event The connect completion event
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
-**/
-VOID
-EslTcp4ConnectComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- )
-{
- BOOLEAN bRemoveFirstPort;
- BOOLEAN bRemovePorts;
- ESL_PORT * pNextPort;
- ESL_SOCKET * pSocket;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the TCP context
- //
- pSocket = pPort->pSocket;
- pTcp4 = &pPort->Context.Tcp4;
-
- //
- // Get the connection status
- //
- bRemoveFirstPort = FALSE;
- bRemovePorts = FALSE;
- Status = pTcp4->ConnectToken.CompletionToken.Status;
- pSocket->ConnectStatus = Status;
- if ( !EFI_ERROR ( Status )) {
- //
- // The connection was successful
- //
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port connected to %d.%d.%d.%d:%d\r\n",
- pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp4->ConfigData.AccessPoint.RemotePort ));
-
- //
- // Start the receive operations
- //
- pSocket->bConfigured = TRUE;
- pSocket->State = SOCKET_STATE_CONNECTED;
- EslSocketRxStart ( pPort );
-
- //
- // Remove the rest of the ports
- //
- bRemovePorts = TRUE;
- }
- else {
- //
- // The connection failed
- //
- if ( pPort->bConfigured ) {
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",
- pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp4->ConfigData.AccessPoint.RemotePort,
- Status ));
- }
-
- //
- // Close the current port
- //
- Status = EslSocketPortClose ( pPort );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port closed\r\n",
- pPort ));
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- }
-
- //
- // Try to connect using the next port
- //
- Status = EslTcp4ConnectStart ( pSocket );
- if ( EFI_NOT_READY != Status ) {
- bRemoveFirstPort = TRUE;
- }
- }
-
- //
- // Remove the ports if necessary
- //
- if ( bRemoveFirstPort || bRemovePorts ) {
- //
- // Remove the first port if necessary
- //
- pPort = pSocket->pPortList;
- if (( !bRemoveFirstPort ) && ( NULL != pPort )) {
- pPort = pPort->pLinkSocket;
- }
-
- //
- // Remove the rest of the list
- //
- while ( NULL != pPort ) {
- pNextPort = pPort->pLinkSocket;
- EslSocketPortClose ( pPort );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port closed\r\n",
- pPort ));
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- }
- pPort = pNextPort;
- }
-
- //
- // Notify the poll routine
- //
- pSocket->bConnected = TRUE;
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Poll for completion of the connection attempt.
-
- This routine polls the ESL_SOCKET::bConnected flag to determine
- when the connection attempt is complete.
-
- This routine is called from ::EslSocketConnect to determine when
- the connection is complete. The ESL_SOCKET::bConnected flag is
- set by ::EslTcp4ConnectComplete when the TCPv4 layer establishes
- a connection or runs out of local network adapters. This routine
- gets the connection status from ESL_SOCKET::ConnectStatus.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS The connection was successfully established.
- @retval EFI_NOT_READY The connection is in progress, call this routine again.
- @retval Others The connection attempt failed.
-
- **/
-EFI_STATUS
-EslTcp4ConnectPoll (
- IN ESL_SOCKET * pSocket
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Determine if the connection is complete
- //
- if ( !pSocket->bConnected ) {
- //
- // Not connected
- //
- pSocket->errno = EAGAIN;
- Status = EFI_NOT_READY;
- }
- else {
- //
- // The connection processing is complete
- //
- pSocket->bConnected = FALSE;
-
- //
- // Translate the connection status
- //
- Status = pSocket->ConnectStatus;
- switch ( Status ) {
- default:
- case EFI_DEVICE_ERROR:
- pSocket->errno = EIO;
- break;
-
- case EFI_ABORTED:
- pSocket->errno = ECONNABORTED;
- break;
-
- case EFI_ACCESS_DENIED:
- pSocket->errno = EACCES;
- break;
-
- case EFI_CONNECTION_RESET:
- pSocket->errno = ECONNRESET;
- break;
-
- case EFI_INVALID_PARAMETER:
- pSocket->errno = EADDRNOTAVAIL;
- break;
-
- case EFI_HOST_UNREACHABLE:
- case EFI_NO_RESPONSE:
- pSocket->errno = EHOSTUNREACH;
- break;
-
- case EFI_NO_MAPPING:
- pSocket->errno = EAFNOSUPPORT;
- break;
-
- case EFI_NO_MEDIA:
- case EFI_NETWORK_UNREACHABLE:
- pSocket->errno = ENETDOWN;
- break;
-
- case EFI_OUT_OF_RESOURCES:
- pSocket->errno = ENOBUFS;
- break;
-
- case EFI_PORT_UNREACHABLE:
- case EFI_PROTOCOL_UNREACHABLE:
- case EFI_CONNECTION_REFUSED:
- pSocket->errno = ECONNREFUSED;
- break;
-
- case EFI_SUCCESS:
- pSocket->errno = 0;
- break;
-
- case EFI_TIMEOUT:
- pSocket->errno = ETIMEDOUT;
- break;
-
- case EFI_UNSUPPORTED:
- pSocket->errno = EOPNOTSUPP;
- break;
- }
-
- //
- // Display the translation
- //
- DEBUG (( DEBUG_CONNECT,
- "ERROR - errno: %d, Status: %r\r\n",
- pSocket->errno,
- Status ));
- }
-
- //
- // Return the initialization status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Attempt to connect to a remote TCP port
-
- This routine starts the connection processing for a SOCK_STREAM
- or SOCK_SEQPAKCET socket using the TCPv4 network layer. It
- configures the local TCPv4 connection point and then attempts to
- connect to a remote system. Upon completion, the
- ::EslTcp4ConnectComplete routine gets called with the connection
- status.
-
- This routine is called by ::EslSocketConnect to initiate the TCPv4
- network specific connect operations. The connection processing is
- initiated by this routine and finished by ::EslTcp4ConnectComplete.
- This pair of routines walks through the list of local TCPv4
- connection points until a connection to the remote system is
- made.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS The connection was successfully established.
- @retval EFI_NOT_READY The connection is in progress, call this routine again.
- @retval Others The connection attempt failed.
-
- **/
-EFI_STATUS
-EslTcp4ConnectStart (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PORT * pPort;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_SIMPLE_NETWORK_MODE SnpModeData;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Determine if any more local adapters are available
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Configure the port
- //
- pTcp4 = &pPort->Context.Tcp4;
- pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;
- pTcp4->ConfigData.TimeToLive = 255;
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->Configure ( pTcp4Protocol,
- &pTcp4->ConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
- Status ));
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port configured\r\n",
- pPort ));
- pPort->bConfigured = TRUE;
-
- //
- // Verify the port connection
- //
- Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,
- NULL,
- NULL,
- NULL,
- NULL,
- &SnpModeData );
- if ( !EFI_ERROR ( Status )) {
- if ( SnpModeData.MediaPresentSupported
- && ( !SnpModeData.MediaPresent )) {
- //
- // Port is not connected to the network
- //
- Status = EFI_NO_MEDIA;
- }
- else {
- //
- // Attempt the connection to the remote system
- //
- Status = pTcp4Protocol->Connect ( pTcp4Protocol,
- &pTcp4->ConnectToken );
- }
- }
- if ( EFI_ERROR ( Status )) {
- //
- // Connection error
- //
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Port 0x%08x not connected, Status: %r\r\n",
- pPort,
- Status ));
- }
- }
- if ( !EFI_ERROR ( Status )) {
- //
- // Connection in progress
- //
- pSocket->errno = EINPROGRESS;
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",
- pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp4->ConfigData.AccessPoint.RemotePort ));
- }
- else {
- //
- // Error return path is through EslTcp4ConnectComplete to
- // enable retry on other ports
- //
- // Status to errno translation gets done in EslTcp4ConnectPoll
- //
- pTcp4->ConnectToken.CompletionToken.Status = Status;
-
- //
- // Continue with the next port
- //
- gBS->CheckEvent ( pTcp4->ConnectToken.CompletionToken.Event );
- gBS->SignalEvent ( pTcp4->ConnectToken.CompletionToken.Event );
- }
- Status = EFI_NOT_READY;
- }
- else {
- //
- // No more local adapters available
- //
- pSocket->errno = ENETUNREACH;
- Status = EFI_NO_RESPONSE;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Establish the known port to listen for network connections.
-
- This routine places the port into a state that enables connection
- attempts.
-
- This routine is called by ::EslSocketListen to handle the network
- specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET
- sockets. See the \ref ConnectionManagement section.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS - Socket successfully created
- @retval Other - Failed to enable the socket for listen
-
-**/
-EFI_STATUS
-EslTcp4Listen (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PORT * pNextPort;
- ESL_PORT * pPort;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Use for/break instead of goto
- //
- for ( ; ; ) {
- //
- // Assume no ports are available
- //
- pSocket->errno = EOPNOTSUPP;
- Status = EFI_NOT_READY;
-
- //
- // Walk the list of ports
- //
- pPort = pSocket->pPortList;
- while ( NULL != pPort ) {
- //
- // Assume success
- //
- pSocket->errno = 0;
-
- //
- // Use for/break insteak of goto
- //
- for ( ; ; ) {
- //
- // Create the listen completion event
- //
- pTcp4 = &pPort->Context.Tcp4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcp4ListenComplete,
- pPort,
- &pTcp4->ListenToken.CompletionToken.Event );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,
- "ERROR - Failed to create the listen completion event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_POOL,
- "0x%08x: Created listen completion event\r\n",
- pTcp4->ListenToken.CompletionToken.Event ));
-
- //
- // Configure the port
- //
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->Configure ( pTcp4Protocol,
- &pTcp4->ConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_LISTEN,
- "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
- Status ));
- switch ( Status ) {
- case EFI_ACCESS_DENIED:
- pSocket->errno = EACCES;
- break;
-
- default:
- case EFI_DEVICE_ERROR:
- pSocket->errno = EIO;
- break;
-
- case EFI_INVALID_PARAMETER:
- pSocket->errno = EADDRNOTAVAIL;
- break;
-
- case EFI_NO_MAPPING:
- pSocket->errno = EAFNOSUPPORT;
- break;
-
- case EFI_OUT_OF_RESOURCES:
- pSocket->errno = ENOBUFS;
- break;
-
- case EFI_UNSUPPORTED:
- pSocket->errno = EOPNOTSUPP;
- break;
- }
- break;
- }
- DEBUG (( DEBUG_LISTEN,
- "0x%08x: Port configured\r\n",
- pPort ));
- pPort->bConfigured = TRUE;
-
- //
- // Start the listen operation on the port
- //
- Status = pTcp4Protocol->Accept ( pTcp4Protocol,
- &pTcp4->ListenToken );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_LISTEN,
- "ERROR - Failed Tcp4 accept, Status: %r\r\n",
- Status ));
- switch ( Status ) {
- case EFI_ACCESS_DENIED:
- pSocket->errno = EACCES;
- break;
-
- default:
- case EFI_DEVICE_ERROR:
- pSocket->errno = EIO;
- break;
-
- case EFI_INVALID_PARAMETER:
- pSocket->errno = EADDRNOTAVAIL;
- break;
-
- case EFI_NOT_STARTED:
- pSocket->errno = ENETDOWN;
- break;
-
- case EFI_OUT_OF_RESOURCES:
- pSocket->errno = ENOBUFS;
- break;
- }
- break;
- }
- DEBUG (( DEBUG_LISTEN,
- "0x%08x: Listen pending on Port\r\n",
- pPort ));
-
- //
- // Listen is pending on this port
- //
- break;
- }
-
- //
- // Get the next port
- //
- pNextPort = pPort->pLinkSocket;
-
- //
- // Close the port upon error
- //
- if ( EFI_ERROR ( Status )) {
- EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );
- }
-
- //
- // Set the next port
- //
- pPort = pNextPort;
- }
-
- //
- // Determine if any ports are in the listen state
- //
- if ( NULL == pSocket->pPortList ) {
- //
- // No ports in the listen state
- //
- pSocket->MaxFifoDepth = 0;
-
- //
- // Return the last error detected
- //
- break;
- }
-
- //
- // Mark the socket as configured
- //
- pSocket->bConfigured = TRUE;
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
-
- //
- // All done
- //
- DEBUG (( DEBUG_LISTEN,
- "0x%08x: pSocket - Listen pending on socket\r\n",
- pSocket ));
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Process the connection attempt
-
- A system has initiated a connection attempt with a socket in the
- listen state. Attempt to complete the connection.
-
- The TCPv4 layer calls this routine when a connection is made to
- the socket in the listen state. See the
- \ref ConnectionManagement section.
-
- @param [in] Event The listen completion event
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
-**/
-VOID
-EslTcp4ListenComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- )
-{
- EFI_HANDLE ChildHandle;
- struct sockaddr_in LocalAddress;
- EFI_TCP4_CONFIG_DATA * pConfigData;
- ESL_PORT * pNewPort;
- ESL_SOCKET * pNewSocket;
- ESL_SOCKET * pSocket;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
- EFI_HANDLE TcpPortHandle;
- EFI_STATUS TempStatus;
-
- DBG_ENTER ( );
- VERIFY_AT_TPL ( TPL_SOCKETS );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Determine if this connection fits into the connection FIFO
- //
- pSocket = pPort->pSocket;
- TcpPortHandle = pPort->Context.Tcp4.ListenToken.NewChildHandle;
- if (( SOCKET_STATE_LISTENING == pSocket->State )
- && ( pSocket->MaxFifoDepth > pSocket->FifoDepth )) {
- //
- // Allocate a socket for this connection
- //
- ChildHandle = NULL;
- Status = EslSocketAllocate ( &ChildHandle,
- DEBUG_CONNECTION,
- &pNewSocket );
- if ( !EFI_ERROR ( Status )) {
- //
- // Clone the socket parameters
- //
- pNewSocket->pApi = pSocket->pApi;
- pNewSocket->Domain = pSocket->Domain;
- pNewSocket->Protocol = pSocket->Protocol;
- pNewSocket->Type = pSocket->Type;
-
- //
- // Build the local address
- //
- pTcp4 = &pPort->Context.Tcp4;
- LocalAddress.sin_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength;
- LocalAddress.sin_family = AF_INET;
- LocalAddress.sin_port = 0;
- LocalAddress.sin_addr.s_addr = *(UINT32 *)&pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0];
-
- //
- // Allocate a port for this connection
- // Note in this instance Configure may not be called with NULL!
- //
- Status = EslSocketPortAllocate ( pNewSocket,
- pPort->pService,
- TcpPortHandle,
- (struct sockaddr *)&LocalAddress,
- FALSE,
- DEBUG_CONNECTION,
- &pNewPort );
- if ( !EFI_ERROR ( Status )) {
- //
- // Restart the listen operation on the port
- //
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->Accept ( pTcp4Protocol,
- &pTcp4->ListenToken );
-
- //
- // Close the TCP port using SocketClose
- //
- TcpPortHandle = NULL;
- pTcp4 = &pNewPort->Context.Tcp4;
-
- //
- // Check for an accept call error
- //
- if ( !EFI_ERROR ( Status )) {
- //
- // Get the port configuration
- //
- pNewPort->bConfigured = TRUE;
- pConfigData = &pTcp4->ConfigData;
- pConfigData->ControlOption = &pTcp4->Option;
- pTcp4Protocol = pNewPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,
- NULL,
- pConfigData,
- NULL,
- NULL,
- NULL );
- if ( !EFI_ERROR ( Status )) {
- //
- // Add the new socket to the connection FIFO
- //
- if ( NULL == pSocket->pFifoTail ) {
- //
- // First connection
- //
- pSocket->pFifoHead = pNewSocket;
- }
- else {
- //
- // Add to end of list.
- //
- pSocket->pFifoTail->pNextConnection = pNewSocket;
- }
- pSocket->pFifoTail = pNewSocket;
- pSocket->FifoDepth += 1;
-
- //
- // Update the socket state
- //
- pNewSocket->State = SOCKET_STATE_IN_FIFO;
-
- //
- // Log the connection
- //
- DEBUG (( DEBUG_CONNECTION | DEBUG_INFO,
- "0x%08x: Socket on port %d.%d.%d.%d:%d connected to %d.%d.%d.%d:%d\r\n",
- pNewSocket,
- pConfigData->AccessPoint.StationAddress.Addr[0],
- pConfigData->AccessPoint.StationAddress.Addr[1],
- pConfigData->AccessPoint.StationAddress.Addr[2],
- pConfigData->AccessPoint.StationAddress.Addr[3],
- pConfigData->AccessPoint.StationPort,
- pConfigData->AccessPoint.RemoteAddress.Addr[0],
- pConfigData->AccessPoint.RemoteAddress.Addr[1],
- pConfigData->AccessPoint.RemoteAddress.Addr[2],
- pConfigData->AccessPoint.RemoteAddress.Addr[3],
- pConfigData->AccessPoint.RemotePort ));
- DEBUG (( DEBUG_CONNECTION | DEBUG_INFO,
- "0x%08x: Listen socket adding socket 0x%08x to FIFO, depth: %d\r\n",
- pSocket,
- pNewSocket,
- pSocket->FifoDepth ));
-
- //
- // Start the receive operation
- //
- EslSocketRxStart ( pNewPort );
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,
- "ERROR - GetModeData failed on port 0x%08x, Status: %r\r\n",
- pNewPort,
- Status ));
- }
- }
- else {
- //
- // The listen failed on this port
- //
- DEBUG (( DEBUG_LISTEN | DEBUG_INFO,
- "ERROR - Listen failed on port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
-
- //
- // Close the listening port
- //
- EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );
- }
- }
-
- //
- // Done with the socket if necessary
- //
- if ( EFI_ERROR ( Status )) {
- TempStatus = EslSocketCloseStart ( &pNewSocket->SocketProtocol,
- TRUE,
- &pSocket->errno );
- ASSERT ( EFI_SUCCESS == TempStatus );
- }
- }
- }
- else {
- DEBUG (( DEBUG_CONNECTION,
- "0x%08x: Socket FIFO full, connection refused\r\n",
- pSocket ));
-
- //
- // The FIFO is full or the socket is in the wrong state
- //
- Status = EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // Close the connection if necessary
- //
- if (( EFI_ERROR ( Status ))
- && ( NULL == TcpPortHandle )) {
- //
- // TODO: Finish this code path
- // The new connection does not fit into the connection FIFO
- //
- // Process:
- // Call close
- // Release the resources
-
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Get the local socket address.
-
- This routine returns the IPv4 address and TCP port number associated
- with the local socket.
-
- This routine is called by ::EslSocketGetLocalAddress to determine the
- network address for the SOCK_STREAM or SOCK_SEQPACKET socket.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @param [out] pSockAddr Network address to receive the local system address
-
-**/
-VOID
-EslTcp4LocalAddressGet (
- IN ESL_PORT * pPort,
- OUT struct sockaddr * pSockAddr
- )
-{
- struct sockaddr_in * pLocalAddress;
- ESL_TCP4_CONTEXT * pTcp4;
-
- DBG_ENTER ( );
-
- //
- // Return the local address
- //
- pTcp4 = &pPort->Context.Tcp4;
- pLocalAddress = (struct sockaddr_in *)pSockAddr;
- pLocalAddress->sin_family = AF_INET;
- pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );
- CopyMem ( &pLocalAddress->sin_addr,
- &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
- sizeof ( pLocalAddress->sin_addr ));
-
- DBG_EXIT ( );
-}
-
-
-/**
- Set the local port address.
-
- This routine sets the local port address.
-
- This support routine is called by ::EslSocketPortAllocate.
-
- @param [in] pPort Address of an ESL_PORT structure
- @param [in] pSockAddr Address of a sockaddr structure that contains the
- connection point on the local machine. An IPv4 address
- of INADDR_ANY specifies that the connection is made to
- all of the network stacks on the platform. Specifying a
- specific IPv4 address restricts the connection to the
- network stack supporting that address. Specifying zero
- for the port causes the network layer to assign a port
- number from the dynamic range. Specifying a specific
- port number causes the network layer to use that port.
-
- @param [in] bBindTest TRUE = run bind testing
-
- @retval EFI_SUCCESS The operation was successful
-
- **/
-EFI_STATUS
-EslTcp4LocalAddressSet (
- IN ESL_PORT * pPort,
- IN CONST struct sockaddr * pSockAddr,
- IN BOOLEAN bBindTest
- )
-{
- EFI_TCP4_ACCESS_POINT * pAccessPoint;
- CONST struct sockaddr_in * pIpAddress;
- CONST UINT8 * pIpv4Address;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Validate the address
- //
- pIpAddress = (struct sockaddr_in *)pSockAddr;
- if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
- //
- // The local address must not be the broadcast address
- //
- Status = EFI_INVALID_PARAMETER;
- pPort->pSocket->errno = EADDRNOTAVAIL;
- }
- else {
- //
- // Set the local address
- //
- pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
- pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
- pAccessPoint->StationAddress.Addr[0] = pIpv4Address[0];
- pAccessPoint->StationAddress.Addr[1] = pIpv4Address[1];
- pAccessPoint->StationAddress.Addr[2] = pIpv4Address[2];
- pAccessPoint->StationAddress.Addr[3] = pIpv4Address[3];
-
- //
- // Determine if the default address is used
- //
- pAccessPoint->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
-
- //
- // Set the subnet mask
- //
- if ( pAccessPoint->UseDefaultAddress ) {
- pAccessPoint->SubnetMask.Addr[0] = 0;
- pAccessPoint->SubnetMask.Addr[1] = 0;
- pAccessPoint->SubnetMask.Addr[2] = 0;
- pAccessPoint->SubnetMask.Addr[3] = 0;
- }
- else {
- pAccessPoint->SubnetMask.Addr[0] = 0xff;
- pAccessPoint->SubnetMask.Addr[1] = ( 128 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;
- pAccessPoint->SubnetMask.Addr[2] = ( 192 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;
- pAccessPoint->SubnetMask.Addr[3] = ( 224 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;
- }
-
- //
- // Validate the IP address
- //
- pAccessPoint->StationPort = 0;
- Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )
- : EFI_SUCCESS;
- if ( !EFI_ERROR ( Status )) {
- //
- // Set the port number
- //
- pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin_port );
- pPort->pSocket->bAddressSet = TRUE;
-
- //
- // Display the local address
- //
- DEBUG (( DEBUG_BIND,
- "0x%08x: Port, Local TCP4 Address: %d.%d.%d.%d:%d\r\n",
- pPort,
- pAccessPoint->StationAddress.Addr[0],
- pAccessPoint->StationAddress.Addr[1],
- pAccessPoint->StationAddress.Addr[2],
- pAccessPoint->StationAddress.Addr[3],
- pAccessPoint->StationPort ));
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Free a receive packet
-
- This routine performs the network specific operations necessary
- to free a receive packet.
-
- This routine is called by ::EslSocketPortCloseTxDone to free a
- receive packet.
-
- @param [in] pPacket Address of an ::ESL_PACKET structure.
- @param [in, out] pRxBytes Address of the count of RX bytes
-
-**/
-VOID
-EslTcp4PacketFree (
- IN ESL_PACKET * pPacket,
- IN OUT size_t * pRxBytes
- )
-{
- DBG_ENTER ( );
-
- //
- // Account for the receive bytes
- //
- *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength;
- DBG_EXIT ( );
-}
-
-
-/**
- Initialize the network specific portions of an ::ESL_PORT structure.
-
- This routine initializes the network specific portions of an
- ::ESL_PORT structure for use by the socket.
-
- This support routine is called by ::EslSocketPortAllocate
- to connect the socket with the underlying network adapter
- running the TCPv4 protocol.
-
- @param [in] pPort Address of an ESL_PORT structure
- @param [in] DebugFlags Flags for debug messages
-
- @retval EFI_SUCCESS - Socket successfully created
-
- **/
-EFI_STATUS
-EslTcp4PortAllocate (
- IN ESL_PORT * pPort,
- IN UINTN DebugFlags
- )
-{
- EFI_TCP4_ACCESS_POINT * pAccessPoint;
- ESL_SOCKET * pSocket;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use for/break instead of goto
- for ( ; ; ) {
- //
- // Allocate the close event
- //
- pSocket = pPort->pSocket;
- pTcp4 = &pPort->Context.Tcp4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete,
- pPort,
- &pTcp4->CloseToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the close event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
- "0x%08x: Created close event\r\n",
- pTcp4->CloseToken.CompletionToken.Event ));
-
- //
- // Allocate the connection event
- //
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcp4ConnectComplete,
- pPort,
- &pTcp4->ConnectToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the connect event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
- "0x%08x: Created connect event\r\n",
- pTcp4->ConnectToken.CompletionToken.Event ));
-
- //
- // Initialize the port
- //
- pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp4Tx.TxData );
- pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Tx.CompletionToken.Event );
- pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP4_IO_TOKEN, Packet.TxData );
-
- //
- // Save the cancel, receive and transmit addresses
- // pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED
- //
- pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv4->Configure;
- pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv4->Poll;
- pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive;
- pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit;
-
- //
- // Set the configuration flags
- //
- pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
- pAccessPoint->ActiveFlag = FALSE;
- pTcp4->ConfigData.TimeToLive = 255;
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Close a TCP4 port.
-
- This routine releases the network specific resources allocated by
- ::EslTcp4PortAllocate.
-
- This routine is called by ::EslSocketPortClose.
- See the \ref PortCloseStateMachine section.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed
- @retval other Port close error
-
-**/
-EFI_STATUS
-EslTcp4PortClose (
- IN ESL_PORT * pPort
- )
-{
- UINTN DebugFlags;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the port in the socket list
- //
- Status = EFI_SUCCESS;
- DebugFlags = pPort->DebugFlags;
- pTcp4 = &pPort->Context.Tcp4;
-
- //
- // Done with the connect event
- //
- if ( NULL != pTcp4->ConnectToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->ConnectToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed connect event\r\n",
- pTcp4->ConnectToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the connect event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the close event
- //
- if ( NULL != pTcp4->CloseToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->CloseToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed close event\r\n",
- pTcp4->CloseToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the close event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the listen completion event
- //
- if ( NULL != pTcp4->ListenToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->ListenToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed listen completion event\r\n",
- pTcp4->ListenToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the listen completion event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Perform the network specific close operation on the port.
-
- This routine performs a cancel operations on the TCPv4 port to
- shutdown the receive operations on the port.
-
- This routine is called by the ::EslSocketPortCloseTxDone
- routine after the port completes all of the transmission.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
-
-**/
-EFI_STATUS
-EslTcp4PortCloseOp (
- IN ESL_PORT * pPort
- )
-{
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Close the configured port
- //
- Status = EFI_SUCCESS;
- pTcp4 = &pPort->Context.Tcp4;
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- pTcp4->CloseToken.AbortOnClose = pPort->bCloseNow;
- Status = pTcp4Protocol->Close ( pTcp4Protocol,
- &pTcp4->CloseToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port close started\r\n",
- pPort ));
- }
- else {
- DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "ERROR - Close failed on port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Receive data from a network connection.
-
- This routine attempts to return buffered data to the caller. The
- data is removed from the urgent queue if the message flag MSG_OOB
- is specified, otherwise data is removed from the normal queue.
- See the \ref ReceiveEngine section.
-
- This routine is called by ::EslSocketReceive to handle the network
- specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET
- sockets.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @param [in] pPacket Address of an ::ESL_PACKET structure.
-
- @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
-
- @param [in] BufferLength Length of the the buffer
-
- @param [in] pBuffer Address of a buffer to receive the data.
-
- @param [in] pDataLength Number of received data bytes in the buffer.
-
- @param [out] pAddress Network address to receive the remote system address
-
- @param [out] pSkipBytes Address to receive the number of bytes skipped
-
- @return Returns the address of the next free byte in the buffer.
-
- **/
-UINT8 *
-EslTcp4Receive (
- IN ESL_PORT * pPort,
- IN ESL_PACKET * pPacket,
- IN BOOLEAN * pbConsumePacket,
- IN size_t BufferLength,
- IN UINT8 * pBuffer,
- OUT size_t * pDataLength,
- OUT struct sockaddr * pAddress,
- OUT size_t * pSkipBytes
- )
-{
- size_t DataLength;
- struct sockaddr_in * pRemoteAddress;
- ESL_TCP4_CONTEXT * pTcp4;
-
- DBG_ENTER ( );
-
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- pTcp4 = &pPort->Context.Tcp4;
- DEBUG (( DEBUG_RX,
- "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp4->ConfigData.AccessPoint.RemotePort ));
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- CopyMem ( &pRemoteAddress->sin_addr,
- &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin_addr ));
- pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
- }
-
- //
- // Determine the amount of received data
- //
- DataLength = pPacket->ValidBytes;
- if ( BufferLength < DataLength ) {
- DataLength = BufferLength;
- }
-
- //
- // Move the data into the buffer
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pPacket,
- pBuffer,
- DataLength ));
- CopyMem ( pBuffer, pPacket->pBuffer, DataLength );
-
- //
- // Set the next buffer address
- //
- pBuffer += DataLength;
-
- //
- // Determine if the data is being read
- //
- if ( *pbConsumePacket ) {
- //
- // Account for the bytes consumed
- //
- pPacket->pBuffer += DataLength;
- pPacket->ValidBytes -= DataLength;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port account for 0x%08x bytes\r\n",
- pPort,
- DataLength ));
-
- //
- // Determine if the entire packet was consumed
- //
- if (( 0 == pPacket->ValidBytes )
- || ( SOCK_STREAM != pPort->pSocket->Type )) {
- //
- // All done with this packet
- // Account for any discarded data
- //
- *pSkipBytes = pPacket->ValidBytes;
- }
- else
- {
- //
- // More data to consume later
- //
- *pbConsumePacket = FALSE;
- }
- }
-
- //
- // Return the data length and the buffer address
- //
- *pDataLength = DataLength;
- DBG_EXIT_HEX ( pBuffer );
- return pBuffer;
-}
-
-
-/**
- Get the remote socket address.
-
- This routine returns the address of the remote connection point
- associated with the SOCK_STREAM or SOCK_SEQPACKET socket.
-
- This routine is called by ::EslSocketGetPeerAddress to detemine
- the TCPv4 address and por number associated with the network adapter.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @param [out] pAddress Network address to receive the remote system address
-
-**/
-VOID
-EslTcp4RemoteAddressGet (
- IN ESL_PORT * pPort,
- OUT struct sockaddr * pAddress
- )
-{
- struct sockaddr_in * pRemoteAddress;
- ESL_TCP4_CONTEXT * pTcp4;
-
- DBG_ENTER ( );
-
- //
- // Return the remote address
- //
- pTcp4 = &pPort->Context.Tcp4;
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- pRemoteAddress->sin_family = AF_INET;
- pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
- CopyMem ( &pRemoteAddress->sin_addr,
- &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin_addr ));
-
- DBG_EXIT ( );
-}
-
-
-/**
- Set the remote address
-
- This routine sets the remote address in the port.
-
- This routine is called by ::EslSocketConnect to specify the
- remote network address.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @param [in] pSockAddr Network address of the remote system.
-
- @param [in] SockAddrLength Length in bytes of the network address.
-
- @retval EFI_SUCCESS The operation was successful
-
- **/
-EFI_STATUS
-EslTcp4RemoteAddressSet (
- IN ESL_PORT * pPort,
- IN CONST struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
- )
-{
- CONST struct sockaddr_in * pRemoteAddress;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Set the remote address
- //
- pTcp4 = &pPort->Context.Tcp4;
- pRemoteAddress = (struct sockaddr_in *)pSockAddr;
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
- pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );
- Status = EFI_SUCCESS;
- if ( INADDR_BROADCAST == pRemoteAddress->sin_addr.s_addr ) {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Invalid remote address\r\n" ));
- Status = EFI_INVALID_PARAMETER;
- pPort->pSocket->errno = EAFNOSUPPORT;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Process the receive completion
-
- This routine queues the data in FIFO order in either the urgent
- or normal data queues depending upon the type of data received.
- See the \ref ReceiveEngine section.
-
- This routine is called by the TCPv4 driver when some data is
- received.
-
- Buffer the data that was just received.
-
- @param [in] Event The receive completion event
-
- @param [in] pIo Address of an ::ESL_IO_MGMT structure
-
-**/
-VOID
-EslTcp4RxComplete (
- IN EFI_EVENT Event,
- IN ESL_IO_MGMT * pIo
- )
-{
- BOOLEAN bUrgent;
- size_t LengthInBytes;
- ESL_PACKET * pPacket;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Get the operation status.
- //
- Status = pIo->Token.Tcp4Rx.CompletionToken.Status;
-
- //
- // +--------------------+ +---------------------------+
- // | ESL_IO_MGMT | | ESL_PACKET |
- // | | | |
- // | +---------------+ +-----------------------+ |
- // | | Token | | EFI_TCP4_RECEIVE_DATA | |
- // | | RxData --> | | |
- // | | | +-----------------------+---+
- // | | Event | | Data Buffer |
- // +----+---------------+ | |
- // | |
- // +---------------------------+
- //
- //
- // Duplicate the buffer address and length for use by the
- // buffer handling code in EslTcp4Receive. These fields are
- // used when a partial read is done of the data from the
- // packet.
- //
- pPacket = pIo->pPacket;
- pPacket->pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
- LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
- pPacket->ValidBytes = LengthInBytes;
-
- //
- // Get the data type so that it may be linked to the
- // correct receive buffer list on the ESL_SOCKET structure
- //
- bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;
-
- //
- // Complete this request
- //
- EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent );
- DBG_EXIT ( );
-}
-
-
-/**
- Start a receive operation
-
- This routine posts a receive buffer to the TCPv4 driver.
- See the \ref ReceiveEngine section.
-
- This support routine is called by EslSocketRxStart.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pIo Address of an ::ESL_IO_MGMT structure.
-
- **/
-VOID
-EslTcp4RxStart (
- IN ESL_PORT * pPort,
- IN ESL_IO_MGMT * pIo
- )
-{
- ESL_PACKET * pPacket;
-
- DBG_ENTER ( );
-
- //
- // Initialize the buffer for receive
- //
- pPacket = pIo->pPacket;
- pIo->Token.Tcp4Rx.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
- pPacket->Op.Tcp4Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp4Rx.Buffer );
- pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;
- pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp4Rx.RxData.DataLength;
- pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer[0];
-
- DBG_EXIT ( );
-}
-
-
-/**
- Determine if the socket is configured.
-
- This routine uses the flag ESL_SOCKET::bConfigured to determine
- if the network layer's configuration routine has been called.
-
- This routine is called by EslSocketIsConfigured to verify
- that the socket has been configured.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS - The port is connected
- @retval EFI_NOT_STARTED - The port is not connected
-
- **/
- EFI_STATUS
- EslTcp4SocketIsConfigured (
- IN ESL_SOCKET * pSocket
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Determine the socket configuration status
- //
- Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;
-
- //
- // Return the port connected state.
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Buffer data for transmission over a network connection.
-
- This routine buffers data for the transmit engine in one of two
- queues, one for urgent (out-of-band) data and the other for normal
- data. The urgent data is provided to TCP as soon as it is available,
- allowing the TCP layer to schedule transmission of the urgent data
- between packets of normal data.
-
- This routine is called by ::EslSocketTransmit to buffer
- data for transmission. When the \ref TransmitEngine has resources,
- this routine will start the transmission of the next buffer on
- the network connection.
-
- Transmission errors are returned during the next transmission or
- during the close operation. Only buffering errors are returned
- during the current transmission attempt.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure
-
- @param [in] Flags Message control flags
-
- @param [in] BufferLength Length of the the buffer
-
- @param [in] pBuffer Address of a buffer to receive the data.
-
- @param [in] pDataLength Number of received data bytes in the buffer.
-
- @param [in] pAddress Network address of the remote system address
-
- @param [in] AddressLength Length of the remote network address structure
-
- @retval EFI_SUCCESS - Socket data successfully buffered
-
- **/
-EFI_STATUS
-EslTcp4TxBuffer (
- IN ESL_SOCKET * pSocket,
- IN int Flags,
- IN size_t BufferLength,
- IN CONST UINT8 * pBuffer,
- OUT size_t * pDataLength,
- IN const struct sockaddr * pAddress,
- IN socklen_t AddressLength
- )
-{
- BOOLEAN bUrgent;
- BOOLEAN bUrgentQueue;
- ESL_PACKET * pPacket;
- ESL_IO_MGMT ** ppActive;
- ESL_IO_MGMT ** ppFree;
- ESL_PORT * pPort;
- ESL_PACKET ** ppQueueHead;
- ESL_PACKET ** ppQueueTail;
- ESL_PACKET * pPreviousPacket;
- size_t * pTxBytes;
- EFI_TCP4_TRANSMIT_DATA * pTxData;
- EFI_STATUS Status;
- EFI_TPL TplPrevious;
-
- DBG_ENTER ( );
-
- //
- // Assume failure
- //
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
- *pDataLength = 0;
-
- //
- // Verify that the socket is connected
- //
- if ( SOCKET_STATE_CONNECTED == pSocket->State ) {
- //
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine the queue head
- //
- bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));
- bUrgentQueue = bUrgent
- && ( !pSocket->bOobInLine )
- && pSocket->pApi->bOobSupported;
- if ( bUrgentQueue ) {
- ppQueueHead = &pSocket->pTxOobPacketListHead;
- ppQueueTail = &pSocket->pTxOobPacketListTail;
- ppActive = &pPort->pTxOobActive;
- ppFree = &pPort->pTxOobFree;
- pTxBytes = &pSocket->TxOobBytes;
- }
- else {
- ppQueueHead = &pSocket->pTxPacketListHead;
- ppQueueTail = &pSocket->pTxPacketListTail;
- ppActive = &pPort->pTxActive;
- ppFree = &pPort->pTxFree;
- pTxBytes = &pSocket->TxBytes;
- }
-
- //
- // Verify that there is enough room to buffer another
- // transmit operation
- //
- if ( pSocket->MaxTxBuf > *pTxBytes ) {
- if ( pPort->bTxFlowControl ) {
- DEBUG (( DEBUG_TX,
- "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n",
- pPort,
- pSocket->MaxTxBuf,
- *pTxBytes ));
- pPort->bTxFlowControl = FALSE;
- }
-
- //
- // Attempt to allocate the packet
- //
- Status = EslSocketPacketAllocate ( &pPacket,
- sizeof ( pPacket->Op.Tcp4Tx )
- - sizeof ( pPacket->Op.Tcp4Tx.Buffer )
- + BufferLength,
- 0,
- DEBUG_TX );
- if ( !EFI_ERROR ( Status )) {
- //
- // Initialize the transmit operation
- //
- pTxData = &pPacket->Op.Tcp4Tx.TxData;
- pTxData->Push = TRUE || bUrgent;
- pTxData->Urgent = bUrgent;
- pTxData->DataLength = (UINT32) BufferLength;
- pTxData->FragmentCount = 1;
- pTxData->FragmentTable[0].FragmentLength = (UINT32) BufferLength;
- pTxData->FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Tx.Buffer[0];
-
- //
- // Copy the data into the buffer
- //
- CopyMem ( &pPacket->Op.Tcp4Tx.Buffer[0],
- pBuffer,
- BufferLength );
-
- //
- // Synchronize with the socket layer
- //
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );
-
- //
- // Stop transmission after an error
- //
- if ( !EFI_ERROR ( pSocket->TxError )) {
- //
- // Display the request
- //
- DEBUG (( DEBUG_TX,
- "Send %d %s bytes from 0x%08x\r\n",
- BufferLength,
- bUrgent ? L"urgent" : L"normal",
- pBuffer ));
-
- //
- // Queue the data for transmission
- //
- pPacket->pNext = NULL;
- pPreviousPacket = *ppQueueTail;
- if ( NULL == pPreviousPacket ) {
- *ppQueueHead = pPacket;
- }
- else {
- pPreviousPacket->pNext = pPacket;
- }
- *ppQueueTail = pPacket;
- DEBUG (( DEBUG_TX,
- "0x%08x: Packet on %s transmit list\r\n",
- pPacket,
- bUrgentQueue ? L"urgent" : L"normal" ));
-
- //
- // Account for the buffered data
- //
- *pTxBytes += BufferLength;
- *pDataLength = BufferLength;
-
- //
- // Start the transmit engine if it is idle
- //
- if ( NULL != *ppFree ) {
- EslSocketTxStart ( pPort,
- ppQueueHead,
- ppQueueTail,
- ppActive,
- ppFree );
- }
- }
- else {
- //
- // Previous transmit error
- // Stop transmission
- //
- Status = pSocket->TxError;
- pSocket->errno = EIO;
-
- //
- // Free the packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_TX );
- }
-
- //
- // Release the socket layer synchronization
- //
- RESTORE_TPL ( TplPrevious );
- }
- else {
- //
- // Packet allocation failed
- //
- pSocket->errno = ENOMEM;
- }
- }
- else {
- if ( !pPort->bTxFlowControl ) {
- DEBUG (( DEBUG_TX,
- "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n",
- pPort,
- pSocket->MaxTxBuf,
- *pTxBytes ));
- pPort->bTxFlowControl = TRUE;
- }
- //
- // Not enough buffer space available
- //
- pSocket->errno = EAGAIN;
- Status = EFI_NOT_READY;
- }
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Process the normal data transmit completion
-
- This routine use ::EslSocketTxComplete to perform the transmit
- completion processing for normal data.
-
- This routine is called by the TCPv4 network layer when a
- normal data transmit request completes.
-
- @param [in] Event The normal transmit completion event
-
- @param [in] pIo The ESL_IO_MGMT structure address
-
-**/
-VOID
-EslTcp4TxComplete (
- IN EFI_EVENT Event,
- IN ESL_IO_MGMT * pIo
- )
-{
- UINT32 LengthInBytes;
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_SOCKET * pSocket;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the active transmit packet
- //
- pPacket = pIo->pPacket;
- pPort = pIo->pPort;
- pSocket = pPort->pSocket;
-
- //
- // Get the transmit length and status
- //
- LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
- pSocket->TxBytes -= LengthInBytes;
- Status = pIo->Token.Tcp4Tx.CompletionToken.Status;
-
- //
- // Complete the transmit operation
- //
- EslSocketTxComplete ( pIo,
- LengthInBytes,
- Status,
- "Normal ",
- &pSocket->pTxPacketListHead,
- &pSocket->pTxPacketListTail,
- &pPort->pTxActive,
- &pPort->pTxFree );
- DBG_EXIT ( );
-}
-
-
-/**
- Process the urgent data transmit completion
-
- This routine use ::EslSocketTxComplete to perform the transmit
- completion processing for urgent data.
-
- This routine is called by the TCPv4 network layer when a
- urgent data transmit request completes.
-
- @param [in] Event The urgent transmit completion event
-
- @param [in] pIo The ESL_IO_MGMT structure address
-
-**/
-VOID
-EslTcp4TxOobComplete (
- IN EFI_EVENT Event,
- IN ESL_IO_MGMT * pIo
- )
-{
- UINT32 LengthInBytes;
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_SOCKET * pSocket;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the active transmit packet
- //
- pPacket = pIo->pPacket;
- pPort = pIo->pPort;
- pSocket = pPort->pSocket;
-
- //
- // Get the transmit length and status
- //
- LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
- pSocket->TxOobBytes -= LengthInBytes;
- Status = pIo->Token.Tcp4Tx.CompletionToken.Status;
-
- //
- // Complete the transmit operation
- //
- EslSocketTxComplete ( pIo,
- LengthInBytes,
- Status,
- "Urgent ",
- &pSocket->pTxOobPacketListHead,
- &pSocket->pTxOobPacketListTail,
- &pPort->pTxOobActive,
- &pPort->pTxOobFree );
- DBG_EXIT ( );
-}
-
-
-/**
- Verify the adapter's IP address
-
- This support routine is called by EslSocketBindTest.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pConfigData Address of the configuration data
-
- @retval EFI_SUCCESS - The IP address is valid
- @retval EFI_NOT_STARTED - The IP address is invalid
-
- **/
-EFI_STATUS
-EslTcp4VerifyLocalIpAddress (
- IN ESL_PORT * pPort,
- IN EFI_TCP4_CONFIG_DATA * pConfigData
- )
-{
- UINTN DataSize;
- EFI_TCP4_ACCESS_POINT * pAccess;
- EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;
- EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;
- ESL_SERVICE * pService;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use break instead of goto
- //
- pIfInfo = NULL;
- for ( ; ; ) {
- //
- // Determine if the IP address is specified
- //
- pAccess = &pConfigData->AccessPoint;
- DEBUG (( DEBUG_BIND,
- "UseDefaultAddress: %s\r\n",
- pAccess->UseDefaultAddress ? L"TRUE" : L"FALSE" ));
- DEBUG (( DEBUG_BIND,
- "Requested IP address: %d.%d.%d.%d\r\n",
- pAccess->StationAddress.Addr [ 0 ],
- pAccess->StationAddress.Addr [ 1 ],
- pAccess->StationAddress.Addr [ 2 ],
- pAccess->StationAddress.Addr [ 3 ]));
- if ( pAccess->UseDefaultAddress
- || (( 0 == pAccess->StationAddress.Addr [ 0 ])
- && ( 0 == pAccess->StationAddress.Addr [ 1 ])
- && ( 0 == pAccess->StationAddress.Addr [ 2 ])
- && ( 0 == pAccess->StationAddress.Addr [ 3 ])))
- {
- Status = EFI_SUCCESS;
- break;
- }
-
- //
- // Open the configuration protocol
- //
- pService = pPort->pService;
- Status = gBS->OpenProtocol (
- pService->Controller,
- &gEfiIp4Config2ProtocolGuid,
- (VOID **)&pIpConfig2Protocol,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
- Status ));
- break;
- }
-
- //
- // Get the interface information size.
- //
- DataSize = 0;
- Status = pIpConfig2Protocol->GetData (
- pIpConfig2Protocol,
- Ip4Config2DataTypeInterfaceInfo,
- &DataSize,
- NULL
- );
- if ( EFI_BUFFER_TOO_SMALL != Status ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Failed to get the interface information size, Status: %r\r\n",
- Status ));
- break;
- }
-
- //
- // Allocate the interface information buffer
- //
- pIfInfo = AllocatePool ( DataSize );
- if ( NULL == pIfInfo ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
- Status = EFI_OUT_OF_RESOURCES;
- break;
- }
-
- //
- // Get the interface info.
- //
- Status = pIpConfig2Protocol->GetData (
- pIpConfig2Protocol,
- Ip4Config2DataTypeInterfaceInfo,
- &DataSize,
- pIfInfo
- );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Failed to return the interface info, Status: %r\r\n",
- Status ));
- break;
- }
-
- //
- // Display the current configuration
- //
- DEBUG (( DEBUG_BIND,
- "Actual adapter IP address: %d.%d.%d.%d\r\n",
- pIfInfo->StationAddress.Addr [ 0 ],
- pIfInfo->StationAddress.Addr [ 1 ],
- pIfInfo->StationAddress.Addr [ 2 ],
- pIfInfo->StationAddress.Addr [ 3 ]));
-
- //
- // Assume the port is not configured
- //
- Status = EFI_SUCCESS;
- if (( pAccess->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])
- && ( pAccess->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])
- && ( pAccess->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])
- && ( pAccess->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {
- break;
- }
-
- //
- // The IP address did not match
- //
- Status = EFI_NOT_STARTED;
- break;
- }
-
- //
- // Free the buffer if necessary
- //
- if ( NULL != pIfInfo ) {
- FreePool ( pIfInfo );
- }
-
- //
- // Return the IP address status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Interface between the socket layer and the network specific
- code that supports SOCK_STREAM and SOCK_SEQPACKET sockets
- over TCPv4.
-**/
-CONST ESL_PROTOCOL_API cEslTcp4Api = {
- "TCPv4",
- IPPROTO_TCP,
- OFFSET_OF ( ESL_PORT, Context.Tcp4.ConfigData ),
- OFFSET_OF ( ESL_LAYER, pTcp4List ),
- OFFSET_OF ( struct sockaddr_in, sin_zero ),
- sizeof ( struct sockaddr_in ),
- AF_INET,
- sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ),
- OFFSET_OF ( ESL_PACKET, Op.Tcp4Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ),
- OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Rx.Packet.RxData ),
- TRUE,
- EADDRINUSE,
- EslTcp4Accept,
- EslTcp4ConnectPoll,
- EslTcp4ConnectStart,
- EslTcp4SocketIsConfigured,
- EslTcp4LocalAddressGet,
- EslTcp4LocalAddressSet,
- EslTcp4Listen,
- NULL, // OptionGet
- NULL, // OptionSet
- EslTcp4PacketFree,
- EslTcp4PortAllocate,
- EslTcp4PortClose,
- EslTcp4PortCloseOp,
- FALSE,
- EslTcp4Receive,
- EslTcp4RemoteAddressGet,
- EslTcp4RemoteAddressSet,
- EslTcp4RxComplete,
- EslTcp4RxStart,
- EslTcp4TxBuffer,
- EslTcp4TxComplete,
- EslTcp4TxOobComplete,
- (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp4VerifyLocalIpAddress
-};