/** @file\r
Implement the IP4 driver support for the socket layer.\r
\r
- Copyright (c) 2011, Intel Corporation\r
- All rights reserved. This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
+ Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
\r
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
**/\r
-\r
#include "Socket.h"\r
\r
\r
-/**\r
- Get the local socket address\r
+/** Get the local socket address.\r
\r
This routine returns the IPv4 address associated with the local\r
socket.\r
network address for the SOCK_RAW socket.\r
\r
@param [in] pPort Address of an ::ESL_PORT structure.\r
-\r
@param [out] pAddress Network address to receive the local system address\r
-\r
**/\r
VOID\r
EslIp4LocalAddressGet (\r
\r
DBG_ENTER ( );\r
\r
- //\r
// Return the local address\r
- //\r
pIp4 = &pPort->Context.Ip4;\r
pLocalAddress = (struct sockaddr_in *)pAddress;\r
pLocalAddress->sin_family = AF_INET;\r
}\r
\r
\r
-/**\r
- Set the local port address.\r
+/** Set the local port address.\r
\r
This routine sets the local port address.\r
\r
@param [in] bBindTest TRUE = run bind testing\r
\r
@retval EFI_SUCCESS The operation was successful\r
-\r
**/\r
EFI_STATUS\r
EslIp4LocalAddressSet (\r
\r
DBG_ENTER ( );\r
\r
- //\r
// Validate the address\r
- //\r
pIpAddress = (struct sockaddr_in *)pSockAddr;\r
if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
- //\r
// The local address must not be the broadcast address\r
- //\r
Status = EFI_INVALID_PARAMETER;\r
pPort->pSocket->errno = EADDRNOTAVAIL;\r
}\r
else {\r
Status = EFI_SUCCESS;\r
\r
- //\r
// Set the local address\r
- //\r
pIpAddress = (struct sockaddr_in *)pSockAddr;\r
pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;\r
pConfig = &pPort->Context.Ip4.ModeData.ConfigData;\r
pConfig->StationAddress.Addr[2] = pIpv4Address[2];\r
pConfig->StationAddress.Addr[3] = pIpv4Address[3];\r
\r
- //\r
// Determine if the default address is used\r
- //\r
pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
\r
- //\r
// Display the local address\r
- //\r
DEBUG (( DEBUG_BIND,\r
"0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",\r
pPort,\r
pConfig->StationAddress.Addr[2],\r
pConfig->StationAddress.Addr[3]));\r
\r
- //\r
// Set the subnet mask\r
- //\r
if ( pConfig->UseDefaultAddress ) {\r
pConfig->SubnetMask.Addr[0] = 0;\r
pConfig->SubnetMask.Addr[1] = 0;\r
pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
}\r
}\r
-\r
- //\r
// Return the operation status\r
- //\r
DBG_EXIT_STATUS ( Status );\r
return Status;\r
}\r
\r
\r
-/**\r
- Get the option value\r
+/** Get the option value.\r
\r
This routine handles the IPv4 level options.\r
\r
@param [out] pOptionLength Buffer to receive the option length\r
\r
@retval EFI_SUCCESS - Socket data successfully received\r
-\r
**/\r
EFI_STATUS\r
EslIp4OptionGet (\r
\r
DBG_ENTER ( );\r
\r
- //\r
// Assume success\r
- //\r
pSocket->errno = 0;\r
Status = EFI_SUCCESS;\r
\r
- //\r
// Attempt to get the option\r
- //\r
switch ( OptionName ) {\r
default:\r
- //\r
// Option not supported\r
- //\r
pSocket->errno = ENOPROTOOPT;\r
Status = EFI_INVALID_PARAMETER;\r
break;\r
*pOptionLength = sizeof ( pSocket->bIncludeHeader );\r
break;\r
}\r
-\r
- //\r
// Return the operation status\r
- //\r
DBG_EXIT_STATUS ( Status );\r
return Status;\r
}\r
\r
\r
-/**\r
- Set the option value\r
+/** Set the option value.\r
\r
This routine handles the IPv4 level options.\r
\r
@param [in] OptionLength Length of the buffer in bytes\r
\r
@retval EFI_SUCCESS - Option successfully set\r
-\r
**/\r
EFI_STATUS\r
EslIp4OptionSet (\r
)\r
{\r
BOOLEAN bTrueFalse;\r
- socklen_t LengthInBytes;\r
- UINT8 * pOptionData;\r
+ //socklen_t LengthInBytes;\r
+ //UINT8 * pOptionData;\r
EFI_STATUS Status;\r
\r
DBG_ENTER ( );\r
\r
- //\r
// Assume success\r
- //\r
pSocket->errno = 0;\r
Status = EFI_SUCCESS;\r
\r
- //\r
// Determine if the option protocol matches\r
- //\r
- LengthInBytes = 0;\r
- pOptionData = NULL;\r
+ //LengthInBytes = 0;\r
+ //pOptionData = NULL;\r
switch ( OptionName ) {\r
default:\r
- //\r
// Protocol level not supported\r
- //\r
DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));\r
pSocket->errno = ENOTSUP;\r
Status = EFI_UNSUPPORTED;\r
\r
case IP_HDRINCL:\r
\r
- //\r
// Validate the option length\r
- //\r
if ( sizeof ( UINT32 ) == OptionLength ) {\r
- //\r
// Restrict the input to TRUE or FALSE\r
- //\r
bTrueFalse = TRUE;\r
if ( 0 == *(UINT32 *)pOptionValue ) {\r
bTrueFalse = FALSE;\r
}\r
pOptionValue = &bTrueFalse;\r
\r
- //\r
// Set the option value\r
- //\r
- pOptionData = (UINT8 *)&pSocket->bIncludeHeader;\r
- LengthInBytes = sizeof ( pSocket->bIncludeHeader );\r
+ //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;\r
+ //LengthInBytes = sizeof ( pSocket->bIncludeHeader );\r
}\r
break;\r
}\r
-\r
- //\r
// Return the operation status\r
- //\r
DBG_EXIT_STATUS ( Status );\r
return Status;\r
}\r
@param [in] pPort Address of an ::ESL_PORT structure.\r
\r
@param [in] pPacket Address of an ::ESL_PACKET structure.\r
- \r
+\r
@param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\r
- \r
+\r
@param [in] BufferLength Length of the the buffer\r
- \r
+\r
@param [in] pBuffer Address of a buffer to receive the data.\r
- \r
+\r
@param [in] pDataLength Number of received data bytes in the buffer.\r
\r
@param [out] pAddress Network address to receive the remote system address\r
)\r
{\r
size_t LengthInBytes;\r
- ESL_PORT * pPort;\r
ESL_PACKET * pPacket;\r
EFI_IP4_RECEIVE_DATA * pRxData;\r
EFI_STATUS Status;\r
- \r
+\r
DBG_ENTER ( );\r
- \r
+\r
//\r
// Get the operation status.\r
//\r
- pPort = pIo->pPort;\r
Status = pIo->Token.Ip4Rx.Status;\r
\r
//\r
pRxData = pIo->Token.Ip4Rx.Packet.RxData;\r
LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;\r
\r
- //\r
+ //{{\r
// +--------------------+ +----------------------+\r
// | ESL_IO_MGMT | | Data Buffer |\r
// | | | (Driver owned) |\r
//\r
//\r
// Save the data in the packet\r
- //\r
+ //}}\r
pPacket = pIo->pPacket;\r
pPacket->Op.Ip4Rx.pRxData = pRxData;\r
\r
that the socket is configured.\r
\r
@param [in] pSocket Address of an ::ESL_SOCKET structure\r
- \r
+\r
@retval EFI_SUCCESS - The port is connected\r
@retval EFI_NOT_STARTED - The port is not connected\r
\r
// Determine the socket configuration status\r
//\r
Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
- \r
+\r
//\r
// Return the port connected state.\r
//\r
RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
\r
//\r
- // Stop transmission after an error\r
+ // Display the request\r
//\r
- if ( !EFI_ERROR ( pSocket->TxError )) {\r
- //\r
- // Display the request\r
- //\r
- DEBUG (( DEBUG_TX,\r
- "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
- BufferLength,\r
- pBuffer,\r
- pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
- pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
- pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
- pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
- pTxData->TxData.DestinationAddress.Addr[0],\r
- pTxData->TxData.DestinationAddress.Addr[1],\r
- pTxData->TxData.DestinationAddress.Addr[2],\r
- pTxData->TxData.DestinationAddress.Addr[3]));\r
-\r
- //\r
- // Queue the data for transmission\r
- //\r
- pPacket->pNext = NULL;\r
- pPreviousPacket = pSocket->pTxPacketListTail;\r
- if ( NULL == pPreviousPacket ) {\r
- pSocket->pTxPacketListHead = pPacket;\r
- }\r
- else {\r
- pPreviousPacket->pNext = pPacket;\r
- }\r
- pSocket->pTxPacketListTail = pPacket;\r
- DEBUG (( DEBUG_TX,\r
- "0x%08x: Packet on transmit list\r\n",\r
- pPacket ));\r
-\r
- //\r
- // Account for the buffered data\r
- //\r
- *pTxBytes += BufferLength;\r
- *pDataLength = BufferLength;\r
+ DEBUG (( DEBUG_TX,\r
+ "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
+ BufferLength,\r
+ pBuffer,\r
+ pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
+ pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
+ pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
+ pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
+ pTxData->TxData.DestinationAddress.Addr[0],\r
+ pTxData->TxData.DestinationAddress.Addr[1],\r
+ pTxData->TxData.DestinationAddress.Addr[2],\r
+ pTxData->TxData.DestinationAddress.Addr[3]));\r
\r
- //\r
- // Start the transmit engine if it is idle\r
- //\r
- if ( NULL != pPort->pTxFree ) {\r
- EslSocketTxStart ( pPort,\r
- &pSocket->pTxPacketListHead,\r
- &pSocket->pTxPacketListTail,\r
- &pPort->pTxActive,\r
- &pPort->pTxFree );\r
- }\r
+ //\r
+ // Queue the data for transmission\r
+ //\r
+ pPacket->pNext = NULL;\r
+ pPreviousPacket = pSocket->pTxPacketListTail;\r
+ if ( NULL == pPreviousPacket ) {\r
+ pSocket->pTxPacketListHead = pPacket;\r
}\r
else {\r
- //\r
- // Previous transmit error\r
- // Stop transmission\r
- //\r
- Status = pSocket->TxError;\r
- pSocket->errno = EIO;\r
+ pPreviousPacket->pNext = pPacket;\r
+ }\r
+ pSocket->pTxPacketListTail = pPacket;\r
+ DEBUG (( DEBUG_TX,\r
+ "0x%08x: Packet on transmit list\r\n",\r
+ pPacket ));\r
+\r
+ //\r
+ // Account for the buffered data\r
+ //\r
+ *pTxBytes += BufferLength;\r
+ *pDataLength = BufferLength;\r
+\r
+ //\r
+ // Start the transmit engine if it is idle\r
+ //\r
+ if ( NULL != pPort->pTxFree ) {\r
+ EslSocketTxStart ( pPort,\r
+ &pSocket->pTxPacketListHead,\r
+ &pSocket->pTxPacketListTail,\r
+ &pPort->pTxActive,\r
+ &pPort->pTxFree );\r
\r
//\r
- // Free the packet\r
+ // Ignore any transmit error\r
//\r
- EslSocketPacketFree ( pPacket, DEBUG_TX );\r
- break;\r
+ if ( EFI_ERROR ( pSocket->TxError )) {\r
+ DEBUG (( DEBUG_TX,\r
+ "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",\r
+ pPort,\r
+ pPacket,\r
+ pSocket->TxError ));\r
+ }\r
+ pSocket->TxError = EFI_SUCCESS;\r
}\r
\r
//\r
ESL_PACKET * pPacket;\r
ESL_SOCKET * pSocket;\r
EFI_STATUS Status;\r
- \r
+\r
DBG_ENTER ( );\r
- \r
+\r
//\r
// Locate the active transmit packet\r
//\r
pSocket->TxBytes -= LengthInBytes;\r
Status = pIo->Token.Ip4Tx.Status;\r
\r
+ //\r
+ // Ignore the transmit error\r
+ //\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_TX,\r
+ "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",\r
+ pPort,\r
+ pPacket,\r
+ Status ));\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
//\r
// Complete the transmit operation\r
//\r
}\r
\r
\r
+/**\r
+ Verify the adapter's IP address\r
+\r
+ This support routine is called by EslSocketBindTest.\r
+\r
+ @param [in] pPort Address of an ::ESL_PORT structure.\r
+ @param [in] pConfigData Address of the configuration data\r
+\r
+ @retval EFI_SUCCESS - The IP address is valid\r
+ @retval EFI_NOT_STARTED - The IP address is invalid\r
+\r
+ **/\r
+EFI_STATUS\r
+EslIp4VerifyLocalIpAddress (\r
+ IN ESL_PORT * pPort,\r
+ IN EFI_IP4_CONFIG_DATA * pConfigData\r
+ )\r
+{\r
+ UINTN DataSize;\r
+ EFI_IP4_IPCONFIG_DATA * pIpConfigData;\r
+ EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;\r
+ ESL_SERVICE * pService;\r
+ EFI_STATUS Status;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Use break instead of goto\r
+ //\r
+ pIpConfigData = NULL;\r
+ for ( ; ; ) {\r
+ //\r
+ // Determine if the IP address is specified\r
+ //\r
+ DEBUG (( DEBUG_BIND,\r
+ "UseDefaultAddress: %s\r\n",\r
+ pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
+ DEBUG (( DEBUG_BIND,\r
+ "Requested IP address: %d.%d.%d.%d\r\n",\r
+ pConfigData->StationAddress.Addr [ 0 ],\r
+ pConfigData->StationAddress.Addr [ 1 ],\r
+ pConfigData->StationAddress.Addr [ 2 ],\r
+ pConfigData->StationAddress.Addr [ 3 ]));\r
+ if ( pConfigData->UseDefaultAddress\r
+ || (( 0 == pConfigData->StationAddress.Addr [ 0 ])\r
+ && ( 0 == pConfigData->StationAddress.Addr [ 1 ])\r
+ && ( 0 == pConfigData->StationAddress.Addr [ 2 ])\r
+ && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))\r
+ {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Open the configuration protocol\r
+ //\r
+ pService = pPort->pService;\r
+ Status = gBS->OpenProtocol ( pService->Controller,\r
+ &gEfiIp4ConfigProtocolGuid,\r
+ (VOID **)&pIpConfigProtocol,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the IP configuration data size\r
+ //\r
+ DataSize = 0;\r
+ Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+ &DataSize,\r
+ NULL );\r
+ if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Allocate the configuration data buffer\r
+ //\r
+ pIpConfigData = AllocatePool ( DataSize );\r
+ if ( NULL == pIpConfigData ) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the IP configuration\r
+ //\r
+ Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+ &DataSize,\r
+ pIpConfigData );\r
+ if ( EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Failed to return IP Configuration data, Status: %r\r\n",\r
+ Status ));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Display the current configuration\r
+ //\r
+ DEBUG (( DEBUG_BIND,\r
+ "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
+ pIpConfigData->StationAddress.Addr [ 0 ],\r
+ pIpConfigData->StationAddress.Addr [ 1 ],\r
+ pIpConfigData->StationAddress.Addr [ 2 ],\r
+ pIpConfigData->StationAddress.Addr [ 3 ]));\r
+\r
+ //\r
+ // Assume the port is not configured\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])\r
+ && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])\r
+ && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])\r
+ && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // The IP address did not match\r
+ //\r
+ Status = EFI_NOT_STARTED;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Free the buffer if necessary\r
+ //\r
+ if ( NULL != pIpConfigData ) {\r
+ FreePool ( pIpConfigData );\r
+ }\r
+\r
+ //\r
+ // Return the IP address status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Interface between the socket layer and the network specific\r
code that supports SOCK_RAW sockets over IPv4.\r
NULL, // RxStart\r
EslIp4TxBuffer,\r
EslIp4TxComplete,\r
- NULL // TxOobComplete\r
+ NULL, // TxOobComplete\r
+ (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress\r
};\r