From 2dc09dd50fe30496efe9922ee6177ed7bdef6bc2 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Wed, 20 Nov 2013 18:31:01 +0000 Subject: [PATCH] Ignore transmit errors for UDPv4, UDPv6 and IPv4. Support local bind by validating the IP address using the IP configuration protocol. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Lee Leahy Reviewed-by: Ankit Singh3 git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14875 6f19259b-4bc3-4df7-8a09-765794883524 --- StdLib/EfiSocketLib/EfiSocketLib.inf | 2 + StdLib/EfiSocketLib/Ip4.c | 275 +++++++++++++++---- StdLib/EfiSocketLib/Socket.c | 43 ++- StdLib/EfiSocketLib/Socket.h | 20 ++ StdLib/EfiSocketLib/Tcp4.c | 156 ++++++++++- StdLib/EfiSocketLib/Tcp6.c | 259 +++++++++++++++++- StdLib/EfiSocketLib/Udp4.c | 265 ++++++++++++++---- StdLib/EfiSocketLib/Udp6.c | 391 +++++++++++++++++++++++---- StdLib/Include/Efi/EfiSocketLib.h | 2 + 9 files changed, 1238 insertions(+), 175 deletions(-) diff --git a/StdLib/EfiSocketLib/EfiSocketLib.inf b/StdLib/EfiSocketLib/EfiSocketLib.inf index 5e6ff595a9..a68e241b75 100644 --- a/StdLib/EfiSocketLib/EfiSocketLib.inf +++ b/StdLib/EfiSocketLib/EfiSocketLib.inf @@ -52,6 +52,8 @@ UefiLib [Protocols] + gEfiIp4ConfigProtocolGuid + gEfiIp6ConfigProtocolGuid gEfiIp4ProtocolGuid gEfiIp4ServiceBindingProtocolGuid gEfiIp6ProtocolGuid diff --git a/StdLib/EfiSocketLib/Ip4.c b/StdLib/EfiSocketLib/Ip4.c index 2e832c7ac9..1f7096e7c6 100644 --- a/StdLib/EfiSocketLib/Ip4.c +++ b/StdLib/EfiSocketLib/Ip4.c @@ -1067,71 +1067,64 @@ EslIp4TxBuffer ( RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // - // Stop transmission after an error + // Display the request // - if ( !EFI_ERROR ( pSocket->TxError )) { - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n", - BufferLength, - pBuffer, - pIp4->ModeData.ConfigData.StationAddress.Addr[0], - pIp4->ModeData.ConfigData.StationAddress.Addr[1], - pIp4->ModeData.ConfigData.StationAddress.Addr[2], - pIp4->ModeData.ConfigData.StationAddress.Addr[3], - pTxData->TxData.DestinationAddress.Addr[0], - pTxData->TxData.DestinationAddress.Addr[1], - pTxData->TxData.DestinationAddress.Addr[2], - pTxData->TxData.DestinationAddress.Addr[3])); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; + DEBUG (( DEBUG_TX, + "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n", + BufferLength, + pBuffer, + pIp4->ModeData.ConfigData.StationAddress.Addr[0], + pIp4->ModeData.ConfigData.StationAddress.Addr[1], + pIp4->ModeData.ConfigData.StationAddress.Addr[2], + pIp4->ModeData.ConfigData.StationAddress.Addr[3], + pTxData->TxData.DestinationAddress.Addr[0], + pTxData->TxData.DestinationAddress.Addr[1], + pTxData->TxData.DestinationAddress.Addr[2], + pTxData->TxData.DestinationAddress.Addr[3])); - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - } + // + // Queue the data for transmission + // + pPacket->pNext = NULL; + pPreviousPacket = pSocket->pTxPacketListTail; + if ( NULL == pPreviousPacket ) { + pSocket->pTxPacketListHead = pPacket; } else { - // - // Previous transmit error - // Stop transmission - // - Status = pSocket->TxError; - pSocket->errno = EIO; + pPreviousPacket->pNext = pPacket; + } + pSocket->pTxPacketListTail = pPacket; + DEBUG (( DEBUG_TX, + "0x%08x: Packet on transmit list\r\n", + pPacket )); + + // + // Account for the buffered data + // + *pTxBytes += BufferLength; + *pDataLength = BufferLength; + + // + // Start the transmit engine if it is idle + // + if ( NULL != pPort->pTxFree ) { + EslSocketTxStart ( pPort, + &pSocket->pTxPacketListHead, + &pSocket->pTxPacketListTail, + &pPort->pTxActive, + &pPort->pTxFree ); // - // Free the packet + // Ignore any transmit error // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - break; + if ( EFI_ERROR ( pSocket->TxError )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + pSocket->TxError )); + } + pSocket->TxError = EFI_SUCCESS; } // @@ -1212,6 +1205,18 @@ EslIp4TxComplete ( pSocket->TxBytes -= LengthInBytes; Status = pIo->Token.Ip4Tx.Status; + // + // Ignore the transmit error + // + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + Status )); + Status = EFI_SUCCESS; + } + // // Complete the transmit operation // @@ -1227,6 +1232,157 @@ EslIp4TxComplete ( } +/** + 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 +EslIp4VerifyLocalIpAddress ( + IN ESL_PORT * pPort, + IN EFI_IP4_CONFIG_DATA * pConfigData + ) +{ + UINTN DataSize; + EFI_IP4_IPCONFIG_DATA * pIpConfigData; + EFI_IP4_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 + // + DEBUG (( DEBUG_BIND, + "UseDefaultAddress: %s\r\n", + pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" )); + DEBUG (( DEBUG_BIND, + "Requested IP address: %d.%d.%d.%d\r\n", + pConfigData->StationAddress.Addr [ 0 ], + pConfigData->StationAddress.Addr [ 1 ], + pConfigData->StationAddress.Addr [ 2 ], + pConfigData->StationAddress.Addr [ 3 ])); + if ( pConfigData->UseDefaultAddress + || (( 0 == pConfigData->StationAddress.Addr [ 0 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 3 ]))) + { + Status = EFI_SUCCESS; + break; + } + + // + // Open the configuration protocol + // + pService = pPort->pService; + Status = gBS->OpenProtocol ( pService->Controller, + &gEfiIp4ConfigProtocolGuid, + (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, + &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, + &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: %d.%d.%d.%d\r\n", + pIpConfigData->StationAddress.Addr [ 0 ], + pIpConfigData->StationAddress.Addr [ 1 ], + pIpConfigData->StationAddress.Addr [ 2 ], + pIpConfigData->StationAddress.Addr [ 3 ])); + + // + // Assume the port is not configured + // + Status = EFI_SUCCESS; + if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ]) + && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ]) + && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ]) + && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) { + 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_RAW sockets over IPv4. @@ -1265,5 +1421,6 @@ CONST ESL_PROTOCOL_API cEslIp4Api = { NULL, // RxStart EslIp4TxBuffer, EslIp4TxComplete, - NULL // TxOobComplete + NULL, // TxOobComplete + EslIp4VerifyLocalIpAddress }; diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c index a74dcd07f6..b8011951b4 100644 --- a/StdLib/EfiSocketLib/Socket.c +++ b/StdLib/EfiSocketLib/Socket.c @@ -1336,27 +1336,40 @@ EslSocketBindTest ( pConfigData = (VOID *)pBuffer; // - // Attempt to use this configuration + // Validate that the port is connected // - Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData ); + Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_WARN | DEBUG_BIND, - "WARNING - Port 0x%08x failed configuration, Status: %r\r\n", + "WARNING - Port 0x%08x invalid IP address: %r\r\n", pPort, Status )); pPort->pSocket->errno = ErrnoValue; } else { // - // Reset the port + // Attempt to use this configuration // - Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL ); + Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData ); if ( EFI_ERROR ( Status )) { - DEBUG (( DEBUG_ERROR | DEBUG_BIND, - "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n", + DEBUG (( DEBUG_WARN | DEBUG_BIND, + "WARNING - Port 0x%08x failed configuration, Status: %r\r\n", pPort, Status )); - ASSERT ( EFI_SUCCESS == Status ); + pPort->pSocket->errno = ErrnoValue; + } + else { + // + // Reset the port + // + Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL ); + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_ERROR | DEBUG_BIND, + "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n", + pPort, + Status )); + ASSERT ( EFI_SUCCESS == Status ); + } } } @@ -5924,10 +5937,24 @@ EslSocketTxStart ( *ppActive = pIo; } else { + // + // Display the transmit error + // + DEBUG (( DEBUG_TX | DEBUG_INFO, + "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n", + pIo, + pPacket, + Status )); if ( EFI_SUCCESS == pSocket->TxError ) { pSocket->TxError = Status; } + // + // Free the IO structure + // + pIo->pNext = *ppFree; + *ppFree = pIo; + // // Discard the transmit buffer // diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h index b38bec6bde..583be1ffd0 100644 --- a/StdLib/EfiSocketLib/Socket.h +++ b/StdLib/EfiSocketLib/Socket.h @@ -920,6 +920,25 @@ VOID IN ESL_IO_MGMT * pIo ); +/** + 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 + + **/ +typedef +EFI_STATUS +(* PFN_API_VERIFY_LOCAL_IP_ADDRESS) ( + IN ESL_PORT * pPort, + IN VOID * pConfigData + ); + /** Socket type control structure @@ -960,6 +979,7 @@ typedef struct { PFN_API_TRANSMIT pfnTransmit; ///< Attempt to buffer a packet for transmit PFN_API_TX_COMPLETE pfnTxComplete; ///< TX completion for normal data PFN_API_TX_COMPLETE pfnTxOobComplete; ///< TX completion for urgent data + PFN_API_VERIFY_LOCAL_IP_ADDRESS pfnVerifyLocalIpAddress; ///< Verify the local IP address } ESL_PROTOCOL_API; diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c index 34e60e2a7f..1e1d62a7d1 100644 --- a/StdLib/EfiSocketLib/Tcp4.c +++ b/StdLib/EfiSocketLib/Tcp4.c @@ -2225,6 +2225,159 @@ EslTcp4TxOobComplete ( } +/** + 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_IPCONFIG_DATA * pIpConfigData; + EFI_IP4_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, + "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, + &gEfiIp4ConfigProtocolGuid, + (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, + &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, + &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: %d.%d.%d.%d\r\n", + pIpConfigData->StationAddress.Addr [ 0 ], + pIpConfigData->StationAddress.Addr [ 1 ], + pIpConfigData->StationAddress.Addr [ 2 ], + pIpConfigData->StationAddress.Addr [ 3 ])); + + // + // Assume the port is not configured + // + Status = EFI_SUCCESS; + if (( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ]) + && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ]) + && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ]) + && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) { + 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 @@ -2264,5 +2417,6 @@ CONST ESL_PROTOCOL_API cEslTcp4Api = { EslTcp4RxStart, EslTcp4TxBuffer, EslTcp4TxComplete, - EslTcp4TxOobComplete + EslTcp4TxOobComplete, + EslTcp4VerifyLocalIpAddress }; diff --git a/StdLib/EfiSocketLib/Tcp6.c b/StdLib/EfiSocketLib/Tcp6.c index df70a94f4c..d68cb76cb8 100644 --- a/StdLib/EfiSocketLib/Tcp6.c +++ b/StdLib/EfiSocketLib/Tcp6.c @@ -2294,6 +2294,262 @@ EslTcp6TxOobComplete ( } +/** + 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 @@ -2333,5 +2589,6 @@ CONST ESL_PROTOCOL_API cEslTcp6Api = { EslTcp6RxStart, EslTcp6TxBuffer, EslTcp6TxComplete, - EslTcp6TxOobComplete + EslTcp6TxOobComplete, + EslTcp6VerifyLocalIpAddress }; diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c index 11b7db7614..9ab96ac410 100644 --- a/StdLib/EfiSocketLib/Udp4.c +++ b/StdLib/EfiSocketLib/Udp4.c @@ -867,63 +867,62 @@ EslUdp4TxBuffer ( RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // - // Stop transmission after an error + // Display the request // - if ( !EFI_ERROR ( pSocket->TxError )) { - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d %s bytes from 0x%08x\r\n", - BufferLength, - pBuffer )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; + DEBUG (( DEBUG_TX, + "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n", + BufferLength, + pBuffer, + pTxData->Session.DestinationAddress.Addr[0], + pTxData->Session.DestinationAddress.Addr[1], + pTxData->Session.DestinationAddress.Addr[2], + pTxData->Session.DestinationAddress.Addr[3], + pTxData->Session.DestinationPort )); - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - } + // + // Queue the data for transmission + // + pPacket->pNext = NULL; + pPreviousPacket = pSocket->pTxPacketListTail; + if ( NULL == pPreviousPacket ) { + pSocket->pTxPacketListHead = pPacket; } else { - // - // Previous transmit error - // Stop transmission - // - Status = pSocket->TxError; - pSocket->errno = EIO; + pPreviousPacket->pNext = pPacket; + } + pSocket->pTxPacketListTail = pPacket; + DEBUG (( DEBUG_TX, + "0x%08x: Packet on transmit list\r\n", + pPacket )); + + // + // Account for the buffered data + // + *pTxBytes += BufferLength; + *pDataLength = BufferLength; + + // + // Start the transmit engine if it is idle + // + if ( NULL != pPort->pTxFree ) { + pPacket = pSocket->pTxPacketListHead; + EslSocketTxStart ( pPort, + &pSocket->pTxPacketListHead, + &pSocket->pTxPacketListTail, + &pPort->pTxActive, + &pPort->pTxFree ); // - // Free the packet + // Ignore any transmit error // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - break; + if ( EFI_ERROR ( pSocket->TxError )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + pSocket->TxError )); + } + pSocket->TxError = EFI_SUCCESS; } // @@ -1004,6 +1003,18 @@ EslUdp4TxComplete ( pSocket->TxBytes -= LengthInBytes; Status = pIo->Token.Udp4Tx.Status; + // + // Ignore the transmit error + // + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + Status )); + Status = EFI_SUCCESS; + } + // // Complete the transmit operation // @@ -1019,6 +1030,157 @@ EslUdp4TxComplete ( } +/** + 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 +EslUdp4VerifyLocalIpAddress ( + IN ESL_PORT * pPort, + IN EFI_UDP4_CONFIG_DATA * pConfigData + ) +{ + UINTN DataSize; + EFI_IP4_IPCONFIG_DATA * pIpConfigData; + EFI_IP4_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 + // + DEBUG (( DEBUG_BIND, + "UseDefaultAddress: %s\r\n", + pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" )); + DEBUG (( DEBUG_BIND, + "Requested IP address: %d.%d.%d.%d\r\n", + pConfigData->StationAddress.Addr [ 0 ], + pConfigData->StationAddress.Addr [ 1 ], + pConfigData->StationAddress.Addr [ 2 ], + pConfigData->StationAddress.Addr [ 3 ])); + if ( pConfigData->UseDefaultAddress + || (( 0 == pConfigData->StationAddress.Addr [ 0 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 3 ]))) + { + Status = EFI_SUCCESS; + break; + } + + // + // Open the configuration protocol + // + pService = pPort->pService; + Status = gBS->OpenProtocol ( pService->Controller, + &gEfiIp4ConfigProtocolGuid, + (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, + &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, + &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: %d.%d.%d.%d\r\n", + pIpConfigData->StationAddress.Addr [ 0 ], + pIpConfigData->StationAddress.Addr [ 1 ], + pIpConfigData->StationAddress.Addr [ 2 ], + pIpConfigData->StationAddress.Addr [ 3 ])); + + // + // Assume the port is not configured + // + Status = EFI_SUCCESS; + if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ]) + && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ]) + && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ]) + && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) { + 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_DGRAM sockets over UDPv4. @@ -1057,5 +1219,6 @@ CONST ESL_PROTOCOL_API cEslUdp4Api = { NULL, // RxStart EslUdp4TxBuffer, EslUdp4TxComplete, - NULL // TxOobComplete + NULL, // TxOobComplete + EslUdp4VerifyLocalIpAddress }; diff --git a/StdLib/EfiSocketLib/Udp6.c b/StdLib/EfiSocketLib/Udp6.c index 7de5005096..59b99f84dd 100644 --- a/StdLib/EfiSocketLib/Udp6.c +++ b/StdLib/EfiSocketLib/Udp6.c @@ -609,7 +609,7 @@ EslUdp6RxComplete ( pUdp6Protocol = pPort->pProtocol.UDPv6; pConfigData = &pUdp6->ConfigData; DEBUG (( DEBUG_TX, - "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", + "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", pPort, pConfigData->StationAddress.Addr[0], pConfigData->StationAddress.Addr[1], @@ -627,7 +627,9 @@ EslUdp6RxComplete ( pConfigData->StationAddress.Addr[13], pConfigData->StationAddress.Addr[14], pConfigData->StationAddress.Addr[15], - pConfigData->StationPort, + pConfigData->StationPort )); + DEBUG (( DEBUG_TX, + "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", pConfigData->RemoteAddress.Addr[0], pConfigData->RemoteAddress.Addr[1], pConfigData->RemoteAddress.Addr[2], @@ -692,7 +694,7 @@ EslUdp6RxComplete ( } else { DEBUG (( DEBUG_TX, - "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", + "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ", pPort, pConfigData->StationAddress.Addr[0], pConfigData->StationAddress.Addr[1], @@ -710,7 +712,9 @@ EslUdp6RxComplete ( pConfigData->StationAddress.Addr[13], pConfigData->StationAddress.Addr[14], pConfigData->StationAddress.Addr[15], - pConfigData->StationPort, + pConfigData->StationPort )); + DEBUG (( DEBUG_TX, + "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", pConfigData->RemoteAddress.Addr[0], pConfigData->RemoteAddress.Addr[1], pConfigData->RemoteAddress.Addr[2], @@ -904,63 +908,73 @@ EslUdp6TxBuffer ( RAISE_TPL ( TplPrevious, TPL_SOCKETS ); // - // Stop transmission after an error + // Display the request // - if ( !EFI_ERROR ( pSocket->TxError )) { - // - // Display the request - // - DEBUG (( DEBUG_TX, - "Send %d %s bytes from 0x%08x\r\n", - BufferLength, - pBuffer )); - - // - // Queue the data for transmission - // - pPacket->pNext = NULL; - pPreviousPacket = pSocket->pTxPacketListTail; - if ( NULL == pPreviousPacket ) { - pSocket->pTxPacketListHead = pPacket; - } - else { - pPreviousPacket->pNext = pPacket; - } - pSocket->pTxPacketListTail = pPacket; - DEBUG (( DEBUG_TX, - "0x%08x: Packet on transmit list\r\n", - pPacket )); - - // - // Account for the buffered data - // - *pTxBytes += BufferLength; - *pDataLength = BufferLength; + DEBUG (( DEBUG_TX, + "Send %d bytes from 0x%08x to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", + BufferLength, + pBuffer, + pTxData->Session.DestinationAddress.Addr[0], + pTxData->Session.DestinationAddress.Addr[1], + pTxData->Session.DestinationAddress.Addr[2], + pTxData->Session.DestinationAddress.Addr[3], + pTxData->Session.DestinationAddress.Addr[4], + pTxData->Session.DestinationAddress.Addr[5], + pTxData->Session.DestinationAddress.Addr[6], + pTxData->Session.DestinationAddress.Addr[7], + pTxData->Session.DestinationAddress.Addr[8], + pTxData->Session.DestinationAddress.Addr[9], + pTxData->Session.DestinationAddress.Addr[10], + pTxData->Session.DestinationAddress.Addr[11], + pTxData->Session.DestinationAddress.Addr[12], + pTxData->Session.DestinationAddress.Addr[13], + pTxData->Session.DestinationAddress.Addr[14], + pTxData->Session.DestinationAddress.Addr[15], + pTxData->Session.DestinationPort )); - // - // Start the transmit engine if it is idle - // - if ( NULL != pPort->pTxFree ) { - EslSocketTxStart ( pPort, - &pSocket->pTxPacketListHead, - &pSocket->pTxPacketListTail, - &pPort->pTxActive, - &pPort->pTxFree ); - } + // + // Queue the data for transmission + // + pPacket->pNext = NULL; + pPreviousPacket = pSocket->pTxPacketListTail; + if ( NULL == pPreviousPacket ) { + pSocket->pTxPacketListHead = pPacket; } else { - // - // Previous transmit error - // Stop transmission - // - Status = pSocket->TxError; - pSocket->errno = EIO; + pPreviousPacket->pNext = pPacket; + } + pSocket->pTxPacketListTail = pPacket; + DEBUG (( DEBUG_TX, + "0x%08x: Packet on transmit list\r\n", + pPacket )); + + // + // Account for the buffered data + // + *pTxBytes += BufferLength; + *pDataLength = BufferLength; + + // + // Start the transmit engine if it is idle + // + if ( NULL != pPort->pTxFree ) { + EslSocketTxStart ( pPort, + &pSocket->pTxPacketListHead, + &pSocket->pTxPacketListTail, + &pPort->pTxActive, + &pPort->pTxFree ); // - // Free the packet + // Ignore any transmit error // - EslSocketPacketFree ( pPacket, DEBUG_TX ); - break; + if ( EFI_ERROR ( pSocket->TxError )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + pSocket->TxError )); + } + pSocket->TxError = EFI_SUCCESS; } // @@ -1041,6 +1055,18 @@ EslUdp6TxComplete ( pSocket->TxBytes -= LengthInBytes; Status = pIo->Token.Udp6Tx.Status; + // + // Ignore the transmit error + // + if ( EFI_ERROR ( Status )) { + DEBUG (( DEBUG_TX, + "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n", + pPort, + pPacket, + Status )); + Status = EFI_SUCCESS; + } + // // Complete the transmit operation // @@ -1056,6 +1082,260 @@ EslUdp6TxComplete ( } +/** + 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 +EslUdp6VerifyLocalIpAddress ( + IN ESL_PORT * pPort, + IN EFI_UDP6_CONFIG_DATA * pConfigData + ) +{ + UINTN AddressCount; + EFI_IP6_ADDRESS_INFO * pAddressInfo; + UINTN DataSize; + 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 + // + DEBUG (( DEBUG_BIND, + "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n", + pConfigData->StationAddress.Addr[0], + pConfigData->StationAddress.Addr[1], + pConfigData->StationAddress.Addr[2], + pConfigData->StationAddress.Addr[3], + pConfigData->StationAddress.Addr[4], + pConfigData->StationAddress.Addr[5], + pConfigData->StationAddress.Addr[6], + pConfigData->StationAddress.Addr[7], + pConfigData->StationAddress.Addr[8], + pConfigData->StationAddress.Addr[9], + pConfigData->StationAddress.Addr[10], + pConfigData->StationAddress.Addr[11], + pConfigData->StationAddress.Addr[12], + pConfigData->StationAddress.Addr[13], + pConfigData->StationAddress.Addr[14], + pConfigData->StationAddress.Addr[15])); + if (( 0 == pConfigData->StationAddress.Addr [ 0 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 1 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 2 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 3 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 4 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 5 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 6 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 7 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 8 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 9 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 10 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 11 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 12 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 13 ]) + && ( 0 == pConfigData->StationAddress.Addr [ 14 ]) + && ( 0 == pConfigData->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 ) + && ( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ]) + && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ]) + && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ]) + && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ]) + && ( pConfigData->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ]) + && ( pConfigData->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ]) + && ( pConfigData->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ]) + && ( pConfigData->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ]) + && ( pConfigData->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ]) + && ( pConfigData->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ]) + && ( pConfigData->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ]) + && ( pConfigData->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ]) + && ( pConfigData->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ]) + && ( pConfigData->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ]) + && ( pConfigData->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ]) + && ( pConfigData->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 (( pConfigData->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ]) + && ( pConfigData->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ]) + && ( pConfigData->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ]) + && ( pConfigData->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ]) + && ( pConfigData->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ]) + && ( pConfigData->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ]) + && ( pConfigData->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ]) + && ( pConfigData->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ]) + && ( pConfigData->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ]) + && ( pConfigData->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ]) + && ( pConfigData->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ]) + && ( pConfigData->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ]) + && ( pConfigData->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ]) + && ( pConfigData->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ]) + && ( pConfigData->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ]) + && ( pConfigData->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_DGRAM sockets over UDPv4. @@ -1094,5 +1374,6 @@ CONST ESL_PROTOCOL_API cEslUdp6Api = { NULL, // RxStart EslUdp6TxBuffer, EslUdp6TxComplete, - NULL // TxOobComplete + NULL, // TxOobComplete + EslUdp6VerifyLocalIpAddress }; diff --git a/StdLib/Include/Efi/EfiSocketLib.h b/StdLib/Include/Efi/EfiSocketLib.h index d78e9f6a12..efd6a61b1c 100644 --- a/StdLib/Include/Efi/EfiSocketLib.h +++ b/StdLib/Include/Efi/EfiSocketLib.h @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include #include -- 2.39.2