Skip to content

Commit 4b81c00

Browse files
Merge pull request #1221 from evpopov/BCastAddressDetection_PR
Improves handling of IPv4 broadcast addresses.
2 parents 03d870d + ed2791a commit 4b81c00

28 files changed

+21692
-20564
lines changed

source/FreeRTOS_ARP.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -893,10 +893,11 @@
893893

894894
*( ppxEndPoint ) = NULL;
895895
ulAddressToLookup = *pulIPAddress;
896-
pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulAddressToLookup );
897896

898897
if( xIsIPv4Loopback( ulAddressToLookup ) != 0 )
899898
{
899+
pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulAddressToLookup );
900+
900901
if( pxEndPoint != NULL )
901902
{
902903
/* For multi-cast, use the first IPv4 end-point. */
@@ -925,16 +926,15 @@
925926
}
926927
}
927928
}
928-
else if( ( FreeRTOS_htonl( ulAddressToLookup ) & 0xffU ) == 0xffU ) /* Is this a broadcast address like x.x.x.255 ? */
929+
else if( xIsIPv4Broadcast( ulAddressToLookup, ppxEndPoint ) )
929930
{
930931
/* This is a broadcast so it uses the broadcast MAC address. */
931932
( void ) memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
932-
pxEndPoint = FreeRTOS_FindEndPointOnNetMask( ulAddressToLookup );
933933

934-
if( pxEndPoint != NULL )
935-
{
936-
*( ppxEndPoint ) = pxEndPoint;
937-
}
934+
/* Note that xIsIPv4Broadcast() already filled in ppxEndPoint with the corresponding endpoint
935+
* or the first IPv4 endpoint in case ulAddressToLookup was FREERTOS_INADDR_BROADCAST.
936+
* It is also safe to call xIsIPv4Broadcast() with a null pointer so no need to use
937+
* the intermediary pxEndPoint */
938938

939939
eReturn = eResolutionCacheHit;
940940
}

source/FreeRTOS_DHCP.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@
10471047
const void * pvCopySource = &( pxSet->pucByte[ uxByteIndex ] );
10481048
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxSet->ulParameter ) );
10491049

1050-
if( ( pxSet->ulParameter != FREERTOS_INADDR_ANY ) && ( pxSet->ulParameter != ipBROADCAST_IP_ADDRESS ) )
1050+
if( ( pxSet->ulParameter != FREERTOS_INADDR_ANY ) && ( pxSet->ulParameter != FREERTOS_INADDR_BROADCAST ) )
10511051
{
10521052
EP_IPv4_SETTINGS.ulDNSServerAddresses[ uxTargetIndex ] = pxSet->ulParameter;
10531053
uxTargetIndex++;
@@ -1470,7 +1470,7 @@
14701470
pxEndPoint->xMACAddress.ucBytes, sizeof( MACAddress_t ) );
14711471

14721472
/* Set the addressing. */
1473-
pxAddress->sin_address.ulIP_IPv4 = ipBROADCAST_IP_ADDRESS;
1473+
pxAddress->sin_address.ulIP_IPv4 = FREERTOS_INADDR_BROADCAST;
14741474
pxAddress->sin_port = ( uint16_t ) dhcpSERVER_PORT_IPv4;
14751475
pxAddress->sin_family = FREERTOS_AF_INET4;
14761476
}
@@ -1676,7 +1676,7 @@
16761676
EP_IPv4_SETTINGS.ulIPAddress = EP_DHCPData.ulOfferedIPAddress;
16771677

16781678
/* Setting the 'local' broadcast address, something like 192.168.1.255' */
1679-
EP_IPv4_SETTINGS.ulBroadcastAddress = ( EP_DHCPData.ulOfferedIPAddress & EP_IPv4_SETTINGS.ulNetMask ) | ~EP_IPv4_SETTINGS.ulNetMask;
1679+
EP_IPv4_SETTINGS.ulBroadcastAddress = ( EP_DHCPData.ulOfferedIPAddress | ( ~EP_IPv4_SETTINGS.ulNetMask ) );
16801680

16811681
/* Close socket to ensure packets don't queue on it. not needed anymore as DHCP failed. but still need timer for ARP testing. */
16821682
prvCloseDHCPSocket( pxEndPoint );

source/FreeRTOS_DNS.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,7 @@ const MACAddress_t xMDNS_MacAddressIPv6 = { { 0x33, 0x33, 0x00, 0x00, 0x00, 0xFB
10061006
configASSERT( ucIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT );
10071007
ulIPAddress = pxEndPoint->ipv4_settings.ulDNSServerAddresses[ ucIndex ];
10081008

1009-
if( ( ulIPAddress != 0U ) && ( ulIPAddress != ipBROADCAST_IP_ADDRESS ) )
1009+
if( ( ulIPAddress != 0U ) && ( ulIPAddress != FREERTOS_INADDR_BROADCAST ) )
10101010
{
10111011
pxAddress->sin_family = FREERTOS_AF_INET;
10121012
pxAddress->sin_len = ( uint8_t ) sizeof( struct freertos_sockaddr );

source/FreeRTOS_IPv4.c

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,65 @@ BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress )
210210
}
211211
/*-----------------------------------------------------------*/
212212

213+
/**
214+
* @brief Checks if the IP address matches the global 255.255.255.255 broadcast address or
215+
* the broadcast address for any of our IPv4 endpoints.
216+
*
217+
* @param[in] ulIPAddress The IP address being checked.
218+
*
219+
* @param[out] ppxEndPoint Pointer to an end-point where we store the endpoint whose broadcast address we matched. Or NULL if no IPv4 endpoints were found.
220+
*
221+
* @return pdTRUE if the IP address is a broadcast address or else, pdFALSE.
222+
*/
223+
BaseType_t xIsIPv4Broadcast( uint32_t ulIPAddress,
224+
struct xNetworkEndPoint ** ppxEndPoint )
225+
{
226+
BaseType_t xIsBroadcast;
227+
NetworkEndPoint_t * pxEndPoint;
228+
229+
/* Assign a default answer based on the "global" broadcast. This way
230+
* we can still return the correct result even if there are no endpoints. */
231+
xIsBroadcast = ( ulIPAddress == FREERTOS_INADDR_BROADCAST ) ? pdTRUE : pdFALSE;
232+
233+
for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL );
234+
pxEndPoint != NULL;
235+
pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) )
236+
{
237+
#if ( ipconfigUSE_IPv6 == ipconfigENABLE )
238+
/* Skip over any IPv6 endpoints. */
239+
if( pxEndPoint->bits.bIPv6 == pdTRUE )
240+
{
241+
continue;
242+
}
243+
#endif /* ( ipconfigUSE_IPv6 == ipconfigENABLE ) */
244+
245+
/* If we already know if ulIPAddress is a broadcast,
246+
* simply return this first matching IPv4 endpoint. */
247+
if( xIsBroadcast == pdTRUE )
248+
{
249+
break;
250+
}
251+
else if( ulIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress )
252+
{
253+
xIsBroadcast = pdTRUE;
254+
break;
255+
}
256+
}
257+
258+
/* If the caller wants to know the corresponding endpoint, copy the result.
259+
* Note that this may be null if ulIPAddress is 255.255.255.255 AND there are
260+
* no IPv4 endpoints.
261+
* Also, when ulIPAddress is 255.255.255.255, we will
262+
* return the first IPv4 endpoint that we run across. */
263+
if( xIsBroadcast && ( ppxEndPoint != NULL ) )
264+
{
265+
*ppxEndPoint = pxEndPoint;
266+
}
267+
268+
return xIsBroadcast;
269+
}
270+
/*-----------------------------------------------------------*/
271+
213272
/**
214273
* @brief Check if the packet is an illegal loopback packet.
215274
*
@@ -284,9 +343,11 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
284343
{
285344
/* In systems with a very small amount of RAM, it might be advantageous
286345
* to have incoming messages checked earlier, by the network card driver.
287-
* This method may decrease the usage of sparse network buffers. */
346+
* This method may decrease the usage of scarce network buffers. */
288347
uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
289348
uint32_t ulSourceIPAddress = pxIPHeader->ulSourceIPAddress;
349+
/* Get a reference to the endpoint that the packet was assigned to during pxEasyFit() */
350+
NetworkEndPoint_t * pxEndPoint = pxNetworkBuffer->pxEndPoint;
290351

291352
/* Ensure that the incoming packet is not fragmented because the stack
292353
* doesn't not support IP fragmentation. All but the last fragment coming in will have their
@@ -318,16 +379,20 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
318379
}
319380
}
320381
else if(
321-
( FreeRTOS_FindEndPointOnIP_IPv4( ulDestinationIPAddress ) == NULL ) &&
322-
/* Is it an IPv4 broadcast address x.x.x.255 ? */
323-
( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) &&
382+
/* Not destined for the assigned endpoint IPv4 address? */
383+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulIPAddress ) &&
384+
/* Also not an IPv4 broadcast address ? */
385+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) &&
386+
( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) &&
387+
/* And not an IPv4 multicast address ? */
324388
( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) )
325389
{
326390
/* Packet is not for this node, release it */
327391
eReturn = eReleaseBuffer;
328392
}
329393
/* Is the source address correct? */
330-
else if( ( FreeRTOS_ntohl( ulSourceIPAddress ) & 0xffU ) == 0xffU )
394+
else if( ( ulSourceIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress ) ||
395+
( ulSourceIPAddress == FREERTOS_INADDR_BROADCAST ) )
331396
{
332397
/* The source address cannot be broadcast address. Replying to this
333398
* packet may cause network storms. Drop the packet. */
@@ -336,7 +401,7 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
336401
else if( ( memcmp( xBroadcastMACAddress.ucBytes,
337402
pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes,
338403
sizeof( MACAddress_t ) ) == 0 ) &&
339-
( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) )
404+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) )
340405
{
341406
/* Ethernet address is a broadcast address, but the IP address is not a
342407
* broadcast address. */

source/include/FreeRTOS_IP_Private.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,6 @@ struct xPacketSummary
258258
uint16_t usProtocolBytes; /**< The total length of the protocol data. */
259259
};
260260

261-
#define ipBROADCAST_IP_ADDRESS 0xffffffffU
262-
263261
/* Offset into the Ethernet frame that is used to temporarily store information
264262
* on the fragmentation status of the packet being sent. The value is important,
265263
* as it is past the location into which the destination address will get placed. */

source/include/FreeRTOS_IPv4.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ uint32_t FreeRTOS_GetIPAddress( void );
8484
/* Return pdTRUE if the IPv4 address is a multicast address. */
8585
BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress );
8686

87+
/* Return pdTRUE if the IPv4 address is a broadcast address. */
88+
BaseType_t xIsIPv4Broadcast( uint32_t ulIPAddress,
89+
struct xNetworkEndPoint ** ppxEndPoint );
90+
8791
/* Return pdTRUE if the IPv4 address is a loopback address. */
8892
BaseType_t xIsIPv4Loopback( uint32_t ulAddress );
8993

source/include/FreeRTOS_Sockets.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,10 @@
150150
#if ( ipconfigUSE_TCP == 1 )
151151
#define FREERTOS_SO_SET_LOW_HIGH_WATER ( 18 )
152152
#endif
153-
#define FREERTOS_INADDR_ANY ( 0U ) /* The 0.0.0.0 IPv4 address. */
153+
#define FREERTOS_INADDR_ANY ( 0U ) /* The 0.0.0.0 IPv4 address. */
154+
#define FREERTOS_INADDR_BROADCAST ( 0xffffffffUL ) /* 255.255.255.255 is a special broadcast address that represents all host attached to the physical network. */
154155

155-
#if ( 0 ) /* Not Used */
156+
#if ( 0 ) /* Not Used */
156157
#define FREERTOS_NOT_LAST_IN_FRAGMENTED_PACKET ( 0x80 )
157158
#define FREERTOS_FRAGMENTED_PACKET ( 0x40 )
158159
#endif

source/portable/NetworkInterface/STM32/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ target_sources( freertos_plus_tcp_network_if
2424
Drivers/H7/stm32h7xx_hal_eth.c>
2525
)
2626

27-
target_include_directories( freertos_plus_tcp_network_if
27+
target_include_directories( freertos_plus_tcp_network_if
2828
PUBLIC
2929
$<$<STREQUAL:${FREERTOS_PLUS_TCP_STM32_IF_DRIVER},F4>:
3030
Drivers/F4>

0 commit comments

Comments
 (0)