Skip to content

Commit 6a9f04f

Browse files
authored
Allow use of loopback addresses in IP stack (127.0.0.0/8) (#754)
Authored-by: Adam St. Amand <[email protected]>
1 parent 5b454cd commit 6a9f04f

File tree

5 files changed

+85
-2
lines changed

5 files changed

+85
-2
lines changed

source/FreeRTOS_ARP.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw
413413
const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
414414
const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
415415

416-
if( ( pxIPHeader->ulSourceIPAddress & xNetworkAddressing.ulNetMask ) == ( *ipLOCAL_IP_ADDRESS_POINTER & xNetworkAddressing.ulNetMask ) )
416+
if( ( ( pxIPHeader->ulSourceIPAddress & xNetworkAddressing.ulNetMask ) == ( *ipLOCAL_IP_ADDRESS_POINTER & xNetworkAddressing.ulNetMask ) ) &&
417+
( ( pxIPHeader->ulDestinationIPAddress & ipLOOPBACK_NETMASK ) != ( ipLOOPBACK_ADDRESS & ipLOOPBACK_NETMASK ) ) )
417418
{
418419
/* If the IP is on the same subnet and we do not have an ARP entry already,
419420
* then we should send out ARP for finding the MAC address. */
@@ -726,7 +727,8 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress,
726727
* can be done. */
727728
eReturn = eCantSendPacket;
728729
}
729-
else if( *ipLOCAL_IP_ADDRESS_POINTER == *pulIPAddress )
730+
else if( ( *ipLOCAL_IP_ADDRESS_POINTER == *pulIPAddress ) ||
731+
( ( *pulIPAddress & ipLOOPBACK_NETMASK ) == ( ipLOOPBACK_ADDRESS & ipLOOPBACK_NETMASK ) ) )
730732
{
731733
/* The address of this device. May be useful for the loopback device. */
732734
eReturn = eARPCacheHit;

source/FreeRTOS_IP.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,8 @@ static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPP
14461446
else if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
14471447
/* Is it the global broadcast address 255.255.255.255 ? */
14481448
( ulDestinationIPAddress != ipBROADCAST_IP_ADDRESS ) &&
1449+
/* Is it a loopback address ? */
1450+
( ( ulDestinationIPAddress & ipLOOPBACK_NETMASK ) != ( ipLOOPBACK_ADDRESS & ipLOOPBACK_NETMASK ) ) &&
14491451
/* Is it a specific broadcast address 192.168.1.255 ? */
14501452
( ulDestinationIPAddress != xNetworkAddressing.ulBroadcastAddress ) &&
14511453
#if ( ipconfigUSE_LLMNR == 1 )

source/include/FreeRTOS_IP_Private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ extern const BaseType_t xBufferAllocFixedSize;
387387
* rather than duplicated in its own variable. */
388388
#define ipLOCAL_MAC_ADDRESS ( xDefaultPartUDPPacketHeader.ucBytes )
389389

390+
/* The loopback address block is defined as part of rfc5735 */
391+
#define ipLOOPBACK_ADDRESS ( FreeRTOS_inet_addr_quick( 127, 0, 0, 0 ) )
392+
#define ipLOOPBACK_NETMASK ( FreeRTOS_inet_addr_quick( 255, 0, 0, 0 ) )
393+
390394
/* ICMP packets are sent using the same function as UDP packets. The port
391395
* number is used to distinguish between the two, as 0 is an invalid UDP port. */
392396
#define ipPACKET_CONTAINS_ICMP_DATA ( 0 )

test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_utest.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,29 @@ void test_xCheckRequiresARPResolution_OnLocalNetwork_InCache( void )
945945
TEST_ASSERT_EQUAL( pdFALSE, xResult );
946946
}
947947

948+
void test_xCheckRequiresARPResolution_OnLocalNetwork_Loopback( void )
949+
{
950+
NetworkBufferDescriptor_t xNetworkBuffer, * pxNetworkBuffer;
951+
uint8_t ucEthernetBuffer[ ipconfigNETWORK_MTU ];
952+
BaseType_t xResult;
953+
954+
pxNetworkBuffer = &xNetworkBuffer;
955+
pxNetworkBuffer->pucEthernetBuffer = ucEthernetBuffer;
956+
957+
IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
958+
IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
959+
960+
*ipLOCAL_IP_ADDRESS_POINTER = ipLOOPBACK_ADDRESS;
961+
962+
/* Make sure there is a match on source IP and loopback address */
963+
pxIPHeader->ulDestinationIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;
964+
pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER & xNetworkAddressing.ulNetMask;
965+
966+
xResult = xCheckRequiresARPResolution( pxNetworkBuffer );
967+
968+
TEST_ASSERT_EQUAL( pdFALSE, xResult );
969+
}
970+
948971

949972
void test_ulARPRemoveCacheEntryByMac_NoMatch( void )
950973
{
@@ -1322,6 +1345,23 @@ void test_eARPGetCacheEntry_IPMatchesOtherBroadcastAddr( void )
13221345
/* =================================================== */
13231346
}
13241347

1348+
void test_eARPGetCacheEntry_IPMatchesLoopbackAddr( void )
1349+
{
1350+
uint32_t ulIPAddress;
1351+
MACAddress_t xMACAddress;
1352+
eARPLookupResult_t eResult;
1353+
uint32_t ulSavedGatewayAddress;
1354+
1355+
/* =================================================== */
1356+
ulIPAddress = ipLOOPBACK_ADDRESS;
1357+
/* Not worried about what these functions do. */
1358+
xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL );
1359+
eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress );
1360+
TEST_ASSERT_EQUAL_MESSAGE( eARPCacheHit, eResult, "Test 3" );
1361+
TEST_ASSERT_EQUAL_MEMORY_MESSAGE( &ipLOCAL_MAC_ADDRESS, &xMACAddress, sizeof( xMACAddress ), "Test 3" );
1362+
/* =================================================== */
1363+
}
1364+
13251365
void test_eARPGetCacheEntry_LocalIPIsZero( void )
13261366
{
13271367
uint32_t ulIPAddress;

test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2249,6 +2249,41 @@ void test_prvAllowIPPacket_IncorrectProtocolChecksum( void )
22492249
TEST_ASSERT_EQUAL( eReleaseBuffer, eResult );
22502250
}
22512251

2252+
void test_prvAllowIPPacket_LoopbackDest( void )
2253+
{
2254+
eFrameProcessingResult_t eResult;
2255+
IPPacket_t * pxIPPacket;
2256+
NetworkBufferDescriptor_t * pxNetworkBuffer, xNetworkBuffer;
2257+
UBaseType_t uxHeaderLength = 0;
2258+
uint8_t ucEthBuffer[ ipconfigTCP_MSS ];
2259+
IPHeader_t * pxIPHeader;
2260+
2261+
memset( ucEthBuffer, 0, ipconfigTCP_MSS );
2262+
2263+
pxNetworkBuffer = &xNetworkBuffer;
2264+
pxNetworkBuffer->pucEthernetBuffer = ucEthBuffer;
2265+
pxIPPacket = ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
2266+
pxIPHeader = &( pxIPPacket->xIPHeader );
2267+
2268+
*ipLOCAL_IP_ADDRESS_POINTER = 0xFFFFFFFF;
2269+
2270+
pxIPHeader->ucVersionHeaderLength = 0x45;
2271+
2272+
pxIPHeader->ulDestinationIPAddress = ipLOOPBACK_ADDRESS;
2273+
2274+
memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, &ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
2275+
2276+
pxIPHeader->ulSourceIPAddress = 0xC0C00101;
2277+
2278+
usGenerateChecksum_ExpectAndReturn( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength, ipCORRECT_CRC );
2279+
2280+
usGenerateProtocolChecksum_ExpectAndReturn( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength, pdFALSE, ipCORRECT_CRC );
2281+
2282+
eResult = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
2283+
2284+
TEST_ASSERT_EQUAL( eProcessBuffer, eResult );
2285+
}
2286+
22522287
void test_prvAllowIPPacket_HappyPath( void )
22532288
{
22542289
eFrameProcessingResult_t eResult;

0 commit comments

Comments
 (0)