summaryrefslogtreecommitdiff
path: root/StdLib/EfiSocketLib/Tcp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/EfiSocketLib/Tcp6.c')
-rw-r--r--StdLib/EfiSocketLib/Tcp6.c2596
1 files changed, 0 insertions, 2596 deletions
diff --git a/StdLib/EfiSocketLib/Tcp6.c b/StdLib/EfiSocketLib/Tcp6.c
deleted file mode 100644
index 0f6d2d6ac9..0000000000
--- a/StdLib/EfiSocketLib/Tcp6.c
+++ /dev/null
@@ -1,2596 +0,0 @@
-/** @file
- Implement the TCP6 driver support for the socket layer.
-
- Copyright (c) 2011 - 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.
-
- 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 ::EslTcp6Listen 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 TCPv6 network layer calls
- ::EslTcp6ListenComplete to complete the connection processing.
- EslTcp6ListenComplete 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 ::EslTcp6Accept 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 TCPv6 network layer. It
- configures the local TCPv6 connection point and then attempts to
- connect to a remote system. Upon completion, the
- ::EslTcp6ConnectComplete routine gets called with the connection
- status.
-
- This routine is called by ::EslSocketConnect to initiate the TCPv6
- network specific connect operations. The connection processing is
- initiated by this routine and finished by ::EslTcp6ConnectComplete.
- This pair of routines walks through the list of local TCPv6
- 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
-EslTcp6ConnectStart (
- 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 TCPv6 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
-EslTcp6ListenComplete (
- 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 TCPv6 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
-EslTcp6Accept (
- IN ESL_SOCKET * pSocket,
- IN struct sockaddr * pSockAddr,
- IN OUT socklen_t * pSockAddrLength
- )
-{
- ESL_PORT * pPort;
- struct sockaddr_in6 * pRemoteAddress;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Validate the socket length
- //
- pRemoteAddress = (struct sockaddr_in6 *) 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;
- pTcp6 = &pPort->Context.Tcp6;
-
- //
- // Fill-in the remote address structure
- //
- ZeroMem ( pRemoteAddress, sizeof ( *pRemoteAddress ));
- pRemoteAddress->sin6_len = sizeof ( *pRemoteAddress );
- pRemoteAddress->sin6_family = AF_INET6;
- pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.RemotePort );
- CopyMem ( &pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ],
- &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr ));
- }
-
- //
- // 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 (TCPv6 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 TCPv6 layer when a connect request
- completes. It sets the ESL_SOCKET::bConnected flag to notify the
- ::EslTcp6ConnectComplete 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
-EslTcp6ConnectComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- )
-{
- BOOLEAN bRemoveFirstPort;
- BOOLEAN bRemovePorts;
- ESL_PORT * pNextPort;
- ESL_SOCKET * pSocket;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the TCP context
- //
- pSocket = pPort->pSocket;
- pTcp6 = &pPort->Context.Tcp6;
-
- //
- // Get the connection status
- //
- bRemoveFirstPort = FALSE;
- bRemovePorts = FALSE;
- Status = pTcp6->ConnectToken.CompletionToken.Status;
- pSocket->ConnectStatus = Status;
- if ( !EFI_ERROR ( Status )) {
- //
- // The connection was successful
- //
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
- pPort,
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15],
- pTcp6->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 [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d failed, Status: %r\r\n",
- pPort,
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15],
- pTcp6->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 = EslTcp6ConnectStart ( 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 ::EslTcp6ConnectComplete when the TCPv6 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
-EslTcp6ConnectPoll (
- 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 TCPv6 network layer. It
- configures the local TCPv6 connection point and then attempts to
- connect to a remote system. Upon completion, the
- ::EslTcp6ConnectComplete routine gets called with the connection
- status.
-
- This routine is called by ::EslSocketConnect to initiate the TCPv6
- network specific connect operations. The connection processing is
- initiated by this routine and finished by ::EslTcp6ConnectComplete.
- This pair of routines walks through the list of local TCPv6
- 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
-EslTcp6ConnectStart (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PORT * pPort;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_TCP6_PROTOCOL * pTcp6Protocol;
- 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
- //
- pTcp6 = &pPort->Context.Tcp6;
- pTcp6->ConfigData.AccessPoint.ActiveFlag = TRUE;
- pTcp6->ConfigData.TrafficClass = 0;
- pTcp6->ConfigData.HopLimit = 255;
- pTcp6Protocol = pPort->pProtocol.TCPv6;
- Status = pTcp6Protocol->Configure ( pTcp6Protocol,
- &pTcp6->ConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Failed to configure the Tcp6 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 = pTcp6Protocol->GetModeData ( pTcp6Protocol,
- 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 = pTcp6Protocol->Connect ( pTcp6Protocol,
- &pTcp6->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 [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
- pPort,
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15],
- pTcp6->ConfigData.AccessPoint.RemotePort ));
- }
- else {
- //
- // Error return path is through EslTcp6ConnectComplete to
- // enable retry on other ports
- //
- // Status to errno translation gets done in EslTcp4ConnectPoll
- //
- pTcp6->ConnectToken.CompletionToken.Status = Status;
-
- //
- // Continue with the next port
- //
- gBS->CheckEvent ( pTcp6->ConnectToken.CompletionToken.Event );
- gBS->SignalEvent ( pTcp6->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
-EslTcp6Listen (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PORT * pNextPort;
- ESL_PORT * pPort;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_TCP6_PROTOCOL * pTcp6Protocol;
- 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
- //
- pTcp6 = &pPort->Context.Tcp6;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcp6ListenComplete,
- pPort,
- &pTcp6->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",
- pTcp6->ListenToken.CompletionToken.Event ));
-
- //
- // Configure the port
- //
- pTcp6Protocol = pPort->pProtocol.TCPv6;
- Status = pTcp6Protocol->Configure ( pTcp6Protocol,
- &pTcp6->ConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_LISTEN,
- "ERROR - Failed to configure the Tcp6 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 = pTcp6Protocol->Accept ( pTcp6Protocol,
- &pTcp6->ListenToken );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_LISTEN,
- "ERROR - Failed Tcp6 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 TCPv6 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
-EslTcp6ListenComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- )
-{
- EFI_HANDLE ChildHandle;
- struct sockaddr_in6 LocalAddress;
- EFI_TCP6_CONFIG_DATA * pConfigData;
- ESL_PORT * pNewPort;
- ESL_SOCKET * pNewSocket;
- ESL_SOCKET * pSocket;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_TCP6_PROTOCOL * pTcp6Protocol;
- 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.Tcp6.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
- //
- pTcp6 = &pPort->Context.Tcp6;
- LocalAddress.sin6_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength;
- LocalAddress.sin6_family = AF_INET6;
- LocalAddress.sin6_port = 0;
- CopyMem ( &LocalAddress.sin6_addr.__u6_addr.__u6_addr8 [ 0 ],
- &pTcp6->ConfigData.AccessPoint.StationAddress.Addr [ 0 ],
- sizeof ( pTcp6->ConfigData.AccessPoint.StationAddress.Addr ));
-
- //
- // 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
- //
- pTcp6Protocol = pPort->pProtocol.TCPv6;
- Status = pTcp6Protocol->Accept ( pTcp6Protocol,
- &pTcp6->ListenToken );
-
- //
- // Close the TCP port using SocketClose
- //
- TcpPortHandle = NULL;
- pTcp6 = &pNewPort->Context.Tcp6;
-
- //
- // Check for an accept call error
- //
- if ( !EFI_ERROR ( Status )) {
- //
- // Get the port configuration
- //
- pNewPort->bConfigured = TRUE;
- pConfigData = &pTcp6->ConfigData;
- pConfigData->ControlOption = &pTcp6->Option;
- pTcp6Protocol = pNewPort->pProtocol.TCPv6;
- Status = pTcp6Protocol->GetModeData ( pTcp6Protocol,
- 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 [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%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.StationAddress.Addr[4],
- pConfigData->AccessPoint.StationAddress.Addr[5],
- pConfigData->AccessPoint.StationAddress.Addr[6],
- pConfigData->AccessPoint.StationAddress.Addr[7],
- pConfigData->AccessPoint.StationAddress.Addr[8],
- pConfigData->AccessPoint.StationAddress.Addr[9],
- pConfigData->AccessPoint.StationAddress.Addr[10],
- pConfigData->AccessPoint.StationAddress.Addr[11],
- pConfigData->AccessPoint.StationAddress.Addr[12],
- pConfigData->AccessPoint.StationAddress.Addr[13],
- pConfigData->AccessPoint.StationAddress.Addr[14],
- pConfigData->AccessPoint.StationAddress.Addr[15],
- 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.RemoteAddress.Addr[4],
- pConfigData->AccessPoint.RemoteAddress.Addr[5],
- pConfigData->AccessPoint.RemoteAddress.Addr[6],
- pConfigData->AccessPoint.RemoteAddress.Addr[7],
- pConfigData->AccessPoint.RemoteAddress.Addr[8],
- pConfigData->AccessPoint.RemoteAddress.Addr[9],
- pConfigData->AccessPoint.RemoteAddress.Addr[10],
- pConfigData->AccessPoint.RemoteAddress.Addr[11],
- pConfigData->AccessPoint.RemoteAddress.Addr[12],
- pConfigData->AccessPoint.RemoteAddress.Addr[13],
- pConfigData->AccessPoint.RemoteAddress.Addr[14],
- pConfigData->AccessPoint.RemoteAddress.Addr[15],
- 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 IPv6 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
-EslTcp6LocalAddressGet (
- IN ESL_PORT * pPort,
- OUT struct sockaddr * pSockAddr
- )
-{
- struct sockaddr_in6 * pLocalAddress;
- ESL_TCP6_CONTEXT * pTcp6;
-
- DBG_ENTER ( );
-
- //
- // Return the local address
- //
- pTcp6 = &pPort->Context.Tcp6;
- pLocalAddress = (struct sockaddr_in6 *)pSockAddr;
- pLocalAddress->sin6_family = AF_INET6;
- pLocalAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.StationPort );
- CopyMem ( &pLocalAddress->sin6_addr,
- &pTcp6->ConfigData.AccessPoint.StationAddress.Addr[0],
- sizeof ( pLocalAddress->sin6_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 IPv6 address
- of INADDR_ANY specifies that the connection is made to
- all of the network stacks on the platform. Specifying a
- specific IPv6 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
-EslTcp6LocalAddressSet (
- IN ESL_PORT * pPort,
- IN CONST struct sockaddr * pSockAddr,
- IN BOOLEAN bBindTest
- )
-{
- EFI_TCP6_ACCESS_POINT * pAccessPoint;
- CONST struct sockaddr_in6 * pIpAddress;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Validate the address
- //
- pIpAddress = (struct sockaddr_in6 *)pSockAddr;
-//
-// TODO: Fix the following check
-//
-/*
- if ( INADDR_BROADCAST == pIpAddress->sin6_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
- //
- pAccessPoint = &pPort->Context.Tcp6.ConfigData.AccessPoint;
- CopyMem ( &pAccessPoint->StationAddress.Addr[0],
- &pIpAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ],
- sizeof ( pIpAddress->sin6_addr.__u6_addr.__u6_addr8 [ 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->sin6_port );
- pPort->pSocket->bAddressSet = TRUE;
-
- //
- // Display the local address
- //
- DEBUG (( DEBUG_BIND,
- "0x%08x: Port, Local Tcp6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
- pPort,
- pAccessPoint->StationAddress.Addr[0],
- pAccessPoint->StationAddress.Addr[1],
- pAccessPoint->StationAddress.Addr[2],
- pAccessPoint->StationAddress.Addr[3],
- pAccessPoint->StationAddress.Addr[4],
- pAccessPoint->StationAddress.Addr[5],
- pAccessPoint->StationAddress.Addr[6],
- pAccessPoint->StationAddress.Addr[7],
- pAccessPoint->StationAddress.Addr[8],
- pAccessPoint->StationAddress.Addr[9],
- pAccessPoint->StationAddress.Addr[10],
- pAccessPoint->StationAddress.Addr[11],
- pAccessPoint->StationAddress.Addr[12],
- pAccessPoint->StationAddress.Addr[13],
- pAccessPoint->StationAddress.Addr[14],
- pAccessPoint->StationAddress.Addr[15],
- 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
-EslTcp6PacketFree (
- IN ESL_PACKET * pPacket,
- IN OUT size_t * pRxBytes
- )
-{
- DBG_ENTER ( );
-
- //
- // Account for the receive bytes
- //
- *pRxBytes -= pPacket->Op.Tcp6Rx.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 TCPv6 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
-EslTcp6PortAllocate (
- IN ESL_PORT * pPort,
- IN UINTN DebugFlags
- )
-{
- EFI_TCP6_ACCESS_POINT * pAccessPoint;
- ESL_SOCKET * pSocket;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use for/break instead of goto
- for ( ; ; ) {
- //
- // Allocate the close event
- //
- pSocket = pPort->pSocket;
- pTcp6 = &pPort->Context.Tcp6;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete,
- pPort,
- &pTcp6->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",
- pTcp6->CloseToken.CompletionToken.Event ));
-
- //
- // Allocate the connection event
- //
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcp6ConnectComplete,
- pPort,
- &pTcp6->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",
- pTcp6->ConnectToken.CompletionToken.Event ));
-
- //
- // Initialize the port
- //
- pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp6Tx.TxData );
- pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp6Tx.CompletionToken.Event );
- pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP6_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.TCPv6->Configure;
- pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv6->Poll;
- pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv6->Receive;
- pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv6->Transmit;
-
- //
- // Set the configuration flags
- //
- pAccessPoint = &pPort->Context.Tcp6.ConfigData.AccessPoint;
- pAccessPoint->ActiveFlag = FALSE;
- pTcp6->ConfigData.TrafficClass = 0;
- pTcp6->ConfigData.HopLimit = 255;
- break;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Close a Tcp6 port.
-
- This routine releases the network specific resources allocated by
- ::EslTcp6PortAllocate.
-
- 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
-EslTcp6PortClose (
- IN ESL_PORT * pPort
- )
-{
- UINTN DebugFlags;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Locate the port in the socket list
- //
- Status = EFI_SUCCESS;
- DebugFlags = pPort->DebugFlags;
- pTcp6 = &pPort->Context.Tcp6;
-
- //
- // Done with the connect event
- //
- if ( NULL != pTcp6->ConnectToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp6->ConnectToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed connect event\r\n",
- pTcp6->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 != pTcp6->CloseToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp6->CloseToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed close event\r\n",
- pTcp6->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 != pTcp6->ListenToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp6->ListenToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed listen completion event\r\n",
- pTcp6->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 TCPv6 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
-EslTcp6PortCloseOp (
- IN ESL_PORT * pPort
- )
-{
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_TCP6_PROTOCOL * pTcp6Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Close the configured port
- //
- Status = EFI_SUCCESS;
- pTcp6 = &pPort->Context.Tcp6;
- pTcp6Protocol = pPort->pProtocol.TCPv6;
- pTcp6->CloseToken.AbortOnClose = pPort->bCloseNow;
- Status = pTcp6Protocol->Close ( pTcp6Protocol,
- &pTcp6->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 *
-EslTcp6Receive (
- 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_in6 * pRemoteAddress;
- ESL_TCP6_CONTEXT * pTcp6;
-
- DBG_ENTER ( );
-
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- pTcp6 = &pPort->Context.Tcp6;
- DEBUG (( DEBUG_RX,
- "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[4],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[5],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[6],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[7],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[8],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[9],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[10],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[11],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[12],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[13],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[14],
- pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[15],
- pTcp6->ConfigData.AccessPoint.RemotePort ));
- pRemoteAddress = (struct sockaddr_in6 *)pAddress;
- CopyMem ( &pRemoteAddress->sin6_addr,
- &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin6_addr ));
- pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->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 TCPv6 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
-EslTcp6RemoteAddressGet (
- IN ESL_PORT * pPort,
- OUT struct sockaddr * pAddress
- )
-{
- struct sockaddr_in6 * pRemoteAddress;
- ESL_TCP6_CONTEXT * pTcp6;
-
- DBG_ENTER ( );
-
- //
- // Return the remote address
- //
- pTcp6 = &pPort->Context.Tcp6;
- pRemoteAddress = (struct sockaddr_in6 *)pAddress;
- pRemoteAddress->sin6_family = AF_INET6;
- pRemoteAddress->sin6_port = SwapBytes16 ( pTcp6->ConfigData.AccessPoint.RemotePort );
- CopyMem ( &pRemoteAddress->sin6_addr,
- &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin6_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
-EslTcp6RemoteAddressSet (
- IN ESL_PORT * pPort,
- IN CONST struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
- )
-{
- CONST struct sockaddr_in6 * pRemoteAddress;
- ESL_TCP6_CONTEXT * pTcp6;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Set the remote address
- //
- pTcp6 = &pPort->Context.Tcp6;
- pRemoteAddress = (struct sockaddr_in6 *)pSockAddr;
- CopyMem ( &pTcp6->ConfigData.AccessPoint.RemoteAddress.Addr [ 0 ],
- &pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 [ 0 ],
- sizeof ( pRemoteAddress->sin6_addr.__u6_addr.__u6_addr8 ));
- pTcp6->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin6_port );
- Status = EFI_SUCCESS;
-
-//
-// TODO: Fix the following check
-//
-/*
- if ( INADDR_BROADCAST == pRemoteAddress->sin6_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 TCPv6 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
-EslTcp6RxComplete (
- 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.Tcp6Rx.CompletionToken.Status;
-
- //
- // +--------------------+ +---------------------------+
- // | ESL_IO_MGMT | | ESL_PACKET |
- // | | | |
- // | +---------------+ +-----------------------+ |
- // | | Token | | EFI_Tcp6_RECEIVE_DATA | |
- // | | RxData --> | | |
- // | | | +-----------------------+---+
- // | | Event | | Data Buffer |
- // +----+---------------+ | |
- // | |
- // +---------------------------+
- //
- //
- // Duplicate the buffer address and length for use by the
- // buffer handling code in EslTcp6Receive. These fields are
- // used when a partial read is done of the data from the
- // packet.
- //
- pPacket = pIo->pPacket;
- pPacket->pBuffer = pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentBuffer;
- LengthInBytes = pPacket->Op.Tcp6Rx.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.Tcp6Rx.RxData.UrgentFlag;
-
- //
- // Complete this request
- //
- EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent );
- DBG_EXIT ( );
-}
-
-
-/**
- Start a receive operation
-
- This routine posts a receive buffer to the TCPv6 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
-EslTcp6RxStart (
- IN ESL_PORT * pPort,
- IN ESL_IO_MGMT * pIo
- )
-{
- ESL_PACKET * pPacket;
-
- DBG_ENTER ( );
-
- //
- // Initialize the buffer for receive
- //
- pPacket = pIo->pPacket;
- pIo->Token.Tcp6Rx.Packet.RxData = &pPacket->Op.Tcp6Rx.RxData;
- pPacket->Op.Tcp6Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp6Rx.Buffer );
- pPacket->Op.Tcp6Rx.RxData.FragmentCount = 1;
- pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp6Rx.RxData.DataLength;
- pPacket->Op.Tcp6Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp6Rx.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
- EslTcp6SocketIsConfigured (
- 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
-EslTcp6TxBuffer (
- 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_TCP6_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.Tcp6Tx )
- - sizeof ( pPacket->Op.Tcp6Tx.Buffer )
- + BufferLength,
- 0,
- DEBUG_TX );
- if ( !EFI_ERROR ( Status )) {
- //
- // Initialize the transmit operation
- //
- pTxData = &pPacket->Op.Tcp6Tx.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.Tcp6Tx.Buffer[0];
-
- //
- // Copy the data into the buffer
- //
- CopyMem ( &pPacket->Op.Tcp6Tx.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 TCPv6 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
-EslTcp6TxComplete (
- 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.Tcp6Tx.TxData.DataLength;
- pSocket->TxBytes -= LengthInBytes;
- Status = pIo->Token.Tcp6Tx.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 TCPv6 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
-EslTcp6TxOobComplete (
- 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.Tcp6Tx.TxData.DataLength;
- pSocket->TxOobBytes -= LengthInBytes;
- Status = pIo->Token.Tcp6Tx.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
-EslTcp6VerifyLocalIpAddress (
- IN ESL_PORT * pPort,
- IN EFI_TCP6_CONFIG_DATA * pConfigData
- )
-{
- UINTN AddressCount;
- EFI_IP6_ADDRESS_INFO * pAddressInfo;
- UINTN DataSize;
- EFI_TCP6_ACCESS_POINT * pAccess;
- EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData;
- EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol;
- ESL_SERVICE * pService;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Use break instead of goto
- //
- pIpConfigData = NULL;
- for ( ; ; ) {
- //
- // Determine if the IP address is specified
- //
- pAccess = &pConfigData->AccessPoint;
- DEBUG (( DEBUG_BIND,
- "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
- pAccess->StationAddress.Addr[0],
- pAccess->StationAddress.Addr[1],
- pAccess->StationAddress.Addr[2],
- pAccess->StationAddress.Addr[3],
- pAccess->StationAddress.Addr[4],
- pAccess->StationAddress.Addr[5],
- pAccess->StationAddress.Addr[6],
- pAccess->StationAddress.Addr[7],
- pAccess->StationAddress.Addr[8],
- pAccess->StationAddress.Addr[9],
- pAccess->StationAddress.Addr[10],
- pAccess->StationAddress.Addr[11],
- pAccess->StationAddress.Addr[12],
- pAccess->StationAddress.Addr[13],
- pAccess->StationAddress.Addr[14],
- pAccess->StationAddress.Addr[15]));
- if (( 0 == pAccess->StationAddress.Addr [ 0 ])
- && ( 0 == pAccess->StationAddress.Addr [ 1 ])
- && ( 0 == pAccess->StationAddress.Addr [ 2 ])
- && ( 0 == pAccess->StationAddress.Addr [ 3 ])
- && ( 0 == pAccess->StationAddress.Addr [ 4 ])
- && ( 0 == pAccess->StationAddress.Addr [ 5 ])
- && ( 0 == pAccess->StationAddress.Addr [ 6 ])
- && ( 0 == pAccess->StationAddress.Addr [ 7 ])
- && ( 0 == pAccess->StationAddress.Addr [ 8 ])
- && ( 0 == pAccess->StationAddress.Addr [ 9 ])
- && ( 0 == pAccess->StationAddress.Addr [ 10 ])
- && ( 0 == pAccess->StationAddress.Addr [ 11 ])
- && ( 0 == pAccess->StationAddress.Addr [ 12 ])
- && ( 0 == pAccess->StationAddress.Addr [ 13 ])
- && ( 0 == pAccess->StationAddress.Addr [ 14 ])
- && ( 0 == pAccess->StationAddress.Addr [ 15 ]))
- {
- Status = EFI_SUCCESS;
- break;
- }
-
- //
- // Open the configuration protocol
- //
- pService = pPort->pService;
- Status = gBS->OpenProtocol ( pService->Controller,
- &gEfiIp6ConfigProtocolGuid,
- (VOID **)&pIpConfigProtocol,
- 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 IP configuration data size
- //
- DataSize = 0;
- Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,
- Ip6ConfigDataTypeInterfaceInfo,
- &DataSize,
- NULL );
- if ( EFI_BUFFER_TOO_SMALL != Status ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",
- Status ));
- break;
- }
-
- //
- // Allocate the configuration data buffer
- //
- pIpConfigData = AllocatePool ( DataSize );
- if ( NULL == pIpConfigData ) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));
- Status = EFI_OUT_OF_RESOURCES;
- break;
- }
-
- //
- // Get the IP configuration
- //
- Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,
- Ip6ConfigDataTypeInterfaceInfo,
- &DataSize,
- pIpConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Failed to return IP Configuration data, Status: %r\r\n",
- Status ));
- break;
- }
-
- //
- // Display the current configuration
- //
- DEBUG (( DEBUG_BIND,
- "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
- pIpConfigData->HwAddress.Addr [ 0 ],
- pIpConfigData->HwAddress.Addr [ 1 ],
- pIpConfigData->HwAddress.Addr [ 2 ],
- pIpConfigData->HwAddress.Addr [ 3 ],
- pIpConfigData->HwAddress.Addr [ 4 ],
- pIpConfigData->HwAddress.Addr [ 5 ],
- pIpConfigData->HwAddress.Addr [ 6 ],
- pIpConfigData->HwAddress.Addr [ 7 ],
- pIpConfigData->HwAddress.Addr [ 8 ],
- pIpConfigData->HwAddress.Addr [ 9 ],
- pIpConfigData->HwAddress.Addr [ 10 ],
- pIpConfigData->HwAddress.Addr [ 11 ],
- pIpConfigData->HwAddress.Addr [ 12 ],
- pIpConfigData->HwAddress.Addr [ 13 ],
- pIpConfigData->HwAddress.Addr [ 14 ],
- pIpConfigData->HwAddress.Addr [ 15 ]));
-
- //
- // Validate the hardware address
- //
- Status = EFI_SUCCESS;
- if (( 16 == pIpConfigData->HwAddressSize )
- && ( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ])
- && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ])
- && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ])
- && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ])
- && ( pAccess->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ])
- && ( pAccess->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ])
- && ( pAccess->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ])
- && ( pAccess->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ])
- && ( pAccess->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ])
- && ( pAccess->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ])
- && ( pAccess->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ])
- && ( pAccess->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ])
- && ( pAccess->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ])
- && ( pAccess->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ])
- && ( pAccess->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ])
- && ( pAccess->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) {
- break;
- }
-
- //
- // Walk the list of other IP addresses assigned to this adapter
- //
- for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) {
- pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ];
-
- //
- // Display the IP address
- //
- DEBUG (( DEBUG_BIND,
- "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
- pAddressInfo->Address.Addr [ 0 ],
- pAddressInfo->Address.Addr [ 1 ],
- pAddressInfo->Address.Addr [ 2 ],
- pAddressInfo->Address.Addr [ 3 ],
- pAddressInfo->Address.Addr [ 4 ],
- pAddressInfo->Address.Addr [ 5 ],
- pAddressInfo->Address.Addr [ 6 ],
- pAddressInfo->Address.Addr [ 7 ],
- pAddressInfo->Address.Addr [ 8 ],
- pAddressInfo->Address.Addr [ 9 ],
- pAddressInfo->Address.Addr [ 10 ],
- pAddressInfo->Address.Addr [ 11 ],
- pAddressInfo->Address.Addr [ 12 ],
- pAddressInfo->Address.Addr [ 13 ],
- pAddressInfo->Address.Addr [ 14 ],
- pAddressInfo->Address.Addr [ 15 ]));
-
- //
- // Validate the IP address
- //
- if (( pAccess->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ])
- && ( pAccess->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ])
- && ( pAccess->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ])
- && ( pAccess->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ])
- && ( pAccess->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ])
- && ( pAccess->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ])
- && ( pAccess->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ])
- && ( pAccess->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ])
- && ( pAccess->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ])
- && ( pAccess->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ])
- && ( pAccess->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ])
- && ( pAccess->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ])
- && ( pAccess->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ])
- && ( pAccess->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ])
- && ( pAccess->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ])
- && ( pAccess->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) {
- break;
- }
- }
- if ( pIpConfigData->AddressInfoCount > AddressCount ) {
- break;
- }
-
- //
- // The IP address did not match
- //
- Status = EFI_NOT_STARTED;
- break;
- }
-
- //
- // Free the buffer if necessary
- //
- if ( NULL != pIpConfigData ) {
- FreePool ( pIpConfigData );
- }
-
- //
- // 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 TCPv6.
-**/
-CONST ESL_PROTOCOL_API cEslTcp6Api = {
- "TCPv6",
- IPPROTO_TCP,
- OFFSET_OF ( ESL_PORT, Context.Tcp6.ConfigData ),
- OFFSET_OF ( ESL_LAYER, pTcp6List ),
- sizeof ( struct sockaddr_in6 ),
- sizeof ( struct sockaddr_in6 ),
- AF_INET6,
- sizeof (((ESL_PACKET *)0 )->Op.Tcp6Rx ),
- OFFSET_OF ( ESL_PACKET, Op.Tcp6Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ),
- OFFSET_OF ( ESL_IO_MGMT, Token.Tcp6Rx.Packet.RxData ),
- TRUE,
- EADDRINUSE,
- EslTcp6Accept,
- EslTcp6ConnectPoll,
- EslTcp6ConnectStart,
- EslTcp6SocketIsConfigured,
- EslTcp6LocalAddressGet,
- EslTcp6LocalAddressSet,
- EslTcp6Listen,
- NULL, // OptionGet
- NULL, // OptionSet
- EslTcp6PacketFree,
- EslTcp6PortAllocate,
- EslTcp6PortClose,
- EslTcp6PortCloseOp,
- FALSE,
- EslTcp6Receive,
- EslTcp6RemoteAddressGet,
- EslTcp6RemoteAddressSet,
- EslTcp6RxComplete,
- EslTcp6RxStart,
- EslTcp6TxBuffer,
- EslTcp6TxComplete,
- EslTcp6TxOobComplete,
- (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp6VerifyLocalIpAddress
-};