diff --git a/source/FreeRTOS_IPv4.c b/source/FreeRTOS_IPv4.c index 027a54e2ac..7713478471 100644 --- a/source/FreeRTOS_IPv4.c +++ b/source/FreeRTOS_IPv4.c @@ -378,35 +378,6 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons eReturn = eReleaseBuffer; } } - else if( - /* Not destined for the assigned endpoint IPv4 address? */ - ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulIPAddress ) && - /* Also not an IPv4 broadcast address ? */ - ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && - ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) && - /* And not an IPv4 multicast address ? */ - ( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) ) - { - /* Packet is not for this node, release it */ - eReturn = eReleaseBuffer; - } - /* Is the source address correct? */ - else if( ( ulSourceIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress ) || - ( ulSourceIPAddress == FREERTOS_INADDR_BROADCAST ) ) - { - /* The source address cannot be broadcast address. Replying to this - * packet may cause network storms. Drop the packet. */ - eReturn = eReleaseBuffer; - } - else if( ( memcmp( xBroadcastMACAddress.ucBytes, - pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, - sizeof( MACAddress_t ) ) == 0 ) && - ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) ) - { - /* Ethernet address is a broadcast address, but the IP address is not a - * broadcast address. */ - eReturn = eReleaseBuffer; - } else if( memcmp( xBroadcastMACAddress.ucBytes, pxIPPacket->xEthernetHeader.xSourceAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 ) @@ -419,10 +390,72 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons /* Source is a multicast IP address. Drop the packet in conformity with RFC 1112 section 7.2. */ eReturn = eReleaseBuffer; } + + /* Use ipv4_settings for filtering only after the endpoint is up, + * so that DHCP packets that are exchanged for DHCP (example, DHCP unicast offers) + * are not dropped/filtered. */ + else if( FreeRTOS_IsEndPointUp( pxEndPoint ) != pdFALSE ) + { + if( + /* Not destined for the assigned endpoint IPv4 address? */ + ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulIPAddress ) && + /* Also not an IPv4 broadcast address ? */ + ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && + ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) && + /* And not an IPv4 multicast address ? */ + ( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) ) + { + /* Packet is not for this node, release it */ + eReturn = eReleaseBuffer; + } + /* Is the source address correct? */ + else if( ( ulSourceIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress ) || + ( ulSourceIPAddress == FREERTOS_INADDR_BROADCAST ) ) + { + /* The source address cannot be broadcast address. Replying to this + * packet may cause network storms. Drop the packet. */ + eReturn = eReleaseBuffer; + } + else if( ( memcmp( xBroadcastMACAddress.ucBytes, + pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, + sizeof( MACAddress_t ) ) == 0 ) && + ( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) ) + { + /* Ethernet address is a broadcast address, but the IP address is not a + * broadcast address. */ + eReturn = eReleaseBuffer; + } + else + { + /* Packet is not fragmented, destination is this device, source IP and MAC + * addresses are correct. */ + } + } else { - /* Packet is not fragmented, destination is this device, source IP and MAC - * addresses are correct. */ + /* Endpoint is down */ + + /* RFC 2131: https://datatracker.ietf.org/doc/html/rfc2131#autoid-8 + * The TCP/IP software SHOULD accept and + * forward to the IP layer any IP packets delivered to the client's + * hardware address before the IP address is configured; DHCP servers + * and BOOTP relay agents may not be able to deliver DHCP messages to + * clients that cannot accept hardware unicast datagrams before the + * TCP/IP software is configured. */ + if( ( memcmp( pxEndPoint->xMACAddress.ucBytes, + pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, + sizeof( MACAddress_t ) ) != 0 ) ) + { + /* The endpoint is not up, and the destination MAC address of the + * packet is not matching the endpoint's MAC address. Drop the + * packet. */ + eReturn = eReleaseBuffer; + } + else + { + /* Endpoint is down, but the hardware address matches. Accept the + * packet as per RFC 2131 */ + } } } #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ diff --git a/test/unit-test/FreeRTOS_IPv4/FreeRTOS_IPv4_utest.c b/test/unit-test/FreeRTOS_IPv4/FreeRTOS_IPv4_utest.c index ba9824f4f8..b4b1037b5c 100644 --- a/test/unit-test/FreeRTOS_IPv4/FreeRTOS_IPv4_utest.c +++ b/test/unit-test/FreeRTOS_IPv4/FreeRTOS_IPv4_utest.c @@ -45,6 +45,7 @@ #include "mock_event_groups.h" #include "mock_FreeRTOS_IP.h" +#include "mock_FreeRTOS_IP_Common.h" #include "mock_FreeRTOS_IP_Private.h" #include "mock_FreeRTOS_Routing.h" @@ -396,6 +397,8 @@ void test_prvAllowIPPacketIPv4_NotMatchingIP( void ) pxIPHeader->ucVersionHeaderLength = 0x45; pxIPHeader->ulDestinationIPAddress = pxEndpoint->ipv4_settings.ulIPAddress + 1; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); + eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); @@ -432,6 +435,8 @@ void test_prvAllowIPPacketIPv4_SourceIPBrdCast_DestIPMatch( void ) pxIPHeader->ulSourceIPAddress = 0xFFFFFFFF; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); + eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); @@ -469,6 +474,7 @@ void test_prvAllowIPPacketIPv4_SourceIPBrdCast_DestIPBrdCast( void ) pxIPHeader->ulSourceIPAddress = 0xFFFFFFFF; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); @@ -507,6 +513,7 @@ void test_prvAllowIPPacketIPv4_SourceIPBrdCast_DestIPLLMNR( void ) pxIPHeader->ulSourceIPAddress = 0xFFFFFFFF; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); @@ -541,6 +548,7 @@ void test_prvAllowIPPacketIPv4_SourceIPBrdCast_NoLocalIP( void ) pxIPHeader->ulDestinationIPAddress = 0; pxIPHeader->ulSourceIPAddress = 0xFFFFFFFF; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); @@ -577,6 +585,87 @@ void test_prvAllowIPPacketIPv4_DestMACBrdCast_DestIPUnicast( void ) memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); + + eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); + + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); +} + +/** + * @brief test_prvAllowIPPacketIPv4_EndpointDown_HappyPath + * To validate if prvAllowIPPacketIPv4() returns eProcessBuffer when + * endpoint is down but the destination MAC address matches the MAC address of + * the endpoint. + */ +void test_prvAllowIPPacketIPv4_EndpointDown_HappyPath( void ) +{ + eFrameProcessingResult_t eResult; + IPPacket_t * pxIPPacket; + NetworkBufferDescriptor_t * pxNetworkBuffer, xNetworkBuffer; + UBaseType_t uxHeaderLength = 0; + uint8_t ucEthBuffer[ ipconfigTCP_MSS ]; + IPHeader_t * pxIPHeader; + NetworkEndPoint_t xEndpoint; + + memset( ucEthBuffer, 0, ipconfigTCP_MSS ); + + pxNetworkBuffer = &xNetworkBuffer; + pxNetworkBuffer->pucEthernetBuffer = ucEthBuffer; + pxNetworkBuffer->pxEndPoint = &xEndpoint; + pxIPPacket = ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; + pxIPHeader = &( pxIPPacket->xIPHeader ); + + pxIPHeader->ucVersionHeaderLength = 0x45; + + pxIPHeader->ulDestinationIPAddress = 0x00; + + memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xEndpoint.xMACAddress.ucBytes, sizeof( MACAddress_t ) ); + + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdFALSE ); + FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); + + usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC ); + + usGenerateProtocolChecksum_ExpectAndReturn( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength, pdFALSE, ipCORRECT_CRC ); + + eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); + + TEST_ASSERT_EQUAL( eProcessBuffer, eResult ); +} + +/** + * @brief test_prvAllowIPPacketIPv4_EndpointDown_HappyPath + * To validate if prvAllowIPPacketIPv4() returns eReleaseBuffer when + * endpoint is down but the destination MAC address does not match the MAC address of + * the endpoint. + */ +void test_prvAllowIPPacketIPv4_EndpointDown_UnHappyPath( void ) +{ + eFrameProcessingResult_t eResult; + IPPacket_t * pxIPPacket; + NetworkBufferDescriptor_t * pxNetworkBuffer, xNetworkBuffer; + UBaseType_t uxHeaderLength = 0; + uint8_t ucEthBuffer[ ipconfigTCP_MSS ]; + IPHeader_t * pxIPHeader; + NetworkEndPoint_t xEndpoint; + + memset( ucEthBuffer, 0, ipconfigTCP_MSS ); + + pxNetworkBuffer = &xNetworkBuffer; + pxNetworkBuffer->pucEthernetBuffer = ucEthBuffer; + pxNetworkBuffer->pxEndPoint = &xEndpoint; + pxIPPacket = ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; + pxIPHeader = &( pxIPPacket->xIPHeader ); + + pxIPHeader->ucVersionHeaderLength = 0x45; + + pxIPHeader->ulDestinationIPAddress = 0x00; + + memset( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, 0xAB, sizeof( MACAddress_t ) ); + memset( xEndpoint.xMACAddress.ucBytes, 0xCD, sizeof( MACAddress_t ) ); + + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdFALSE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); @@ -613,6 +702,7 @@ void test_prvAllowIPPacketIPv4_DestMACBrdCast_DestIPBroadcastAndIncorrectChkSum( xEndpoint.ipv4_settings.ulBroadcastAddress = 0xABCDFFFF; memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); @@ -769,6 +859,7 @@ void test_prvAllowIPPacketIPv4_IncorrectChecksum( void ) pxIPHeader->ulSourceIPAddress = 0xC0C00101; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC - 1 ); @@ -812,6 +903,7 @@ void test_prvAllowIPPacketIPv4_IncorrectProtocolChecksum( void ) pxIPHeader->ulSourceIPAddress = 0xC0C00101; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC ); @@ -856,7 +948,7 @@ void test_prvAllowIPPacketIPv4_HappyPath( void ) pxIPHeader->ulSourceIPAddress = 0xC0C00101; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC ); @@ -939,6 +1031,7 @@ void test_prvAllowIPPacketIPv4_DestMacBroadcastIPNotBroadcast( void ) memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); pxIPHeader->ulSourceIPAddress = 0xC0C00101; + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); @@ -1106,6 +1199,8 @@ void test_xBadIPv4Loopback_0_test( void ) memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xMACAddress.ucBytes, sizeof( MACAddress_t ) ); + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); + FreeRTOS_FindEndPointOnMAC_ExpectAnyArgsAndReturn( NULL ); usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC ); diff --git a/test/unit-test/FreeRTOS_IPv4/ut.cmake b/test/unit-test/FreeRTOS_IPv4/ut.cmake index 5d49d53b9c..3319d428e4 100644 --- a/test/unit-test/FreeRTOS_IPv4/ut.cmake +++ b/test/unit-test/FreeRTOS_IPv4/ut.cmake @@ -15,6 +15,7 @@ list(APPEND mock_list "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/queue.h" "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/event_groups.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Common.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Private.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv6.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Routing.h" diff --git a/test/unit-test/FreeRTOS_IPv4_DiffConfig/FreeRTOS_IPv4_DiffConfig_utest.c b/test/unit-test/FreeRTOS_IPv4_DiffConfig/FreeRTOS_IPv4_DiffConfig_utest.c index 4e4c3517f3..69a2fc05a4 100644 --- a/test/unit-test/FreeRTOS_IPv4_DiffConfig/FreeRTOS_IPv4_DiffConfig_utest.c +++ b/test/unit-test/FreeRTOS_IPv4_DiffConfig/FreeRTOS_IPv4_DiffConfig_utest.c @@ -39,6 +39,7 @@ /* This must come after list.h is included (in this case, indirectly * by mock_list.h). */ +#include "mock_FreeRTOS_IP_Common.h" #include "mock_IPv4_DiffConfig_list_macros.h" #include "mock_queue.h" #include "mock_event_groups.h" @@ -105,7 +106,7 @@ void test_prvAllowIPPacketIPv4_BroadcastSourceIP( void ) memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); pxIPHeader->ulSourceIPAddress = 0xFFFFFFFF; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); @@ -146,7 +147,7 @@ void test_prvAllowIPPacketIPv4_BufferLengthLessThanMinimum( void ) pxIPHeader->ulSourceIPAddress = 0xC0C00101; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); @@ -191,7 +192,7 @@ void test_prvAllowIPPacketIPv4_UDPCheckSumZero( void ) pxIPHeader->ulSourceIPAddress = 0xC0C00101; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); @@ -242,7 +243,7 @@ void test_prvAllowIPPacketIPv4_UDP_HappyPath( void ) /* Non-zero checksum. */ pxProtPack->xUDPPacket.xUDPHeader.usChecksum = 0xFF12; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); TEST_ASSERT_EQUAL( eProcessBuffer, eResult ); @@ -286,7 +287,7 @@ void test_prvAllowIPPacketIPv4_TCP_HappyPath( void ) memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); pxIPHeader->ulSourceIPAddress = 0xC0C00101; - + FreeRTOS_IsEndPointUp_ExpectAndReturn( &xEndpoint, pdTRUE ); eResult = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength ); diff --git a/test/unit-test/FreeRTOS_IPv4_DiffConfig/ut.cmake b/test/unit-test/FreeRTOS_IPv4_DiffConfig/ut.cmake index 0b6b4970d7..27a79fac7c 100644 --- a/test/unit-test/FreeRTOS_IPv4_DiffConfig/ut.cmake +++ b/test/unit-test/FreeRTOS_IPv4_DiffConfig/ut.cmake @@ -15,6 +15,7 @@ list(APPEND mock_list "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/queue.h" "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/event_groups.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Common.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Timers.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Utils.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Routing.h" diff --git a/test/unit-test/FreeRTOS_IPv4_DiffConfig1/ut.cmake b/test/unit-test/FreeRTOS_IPv4_DiffConfig1/ut.cmake index 0fa613c7dd..f0f6804e36 100644 --- a/test/unit-test/FreeRTOS_IPv4_DiffConfig1/ut.cmake +++ b/test/unit-test/FreeRTOS_IPv4_DiffConfig1/ut.cmake @@ -17,6 +17,7 @@ list(APPEND mock_list "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Timers.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Utils.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Common.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Routing.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ARP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ICMP.h"