Skip to content

Commit 1f57bb7

Browse files
author
Emil Popov
committed
Improves the detection of IPv4 broadcast addresses.
Add xIsIPv4Broadcast helper function that enumerates over all IPv4 endpoints and their corresponding broadcast addresses. Adds checks for the 255.255.255.255 address. Substitutes ipBROADCAST_IP_ADDRESS with FREERTOS_INADDR_BROADCAST to better match the rest of the world. Cleans up frame filtering a bit to ensure a frame's destination address is NOT matched against other endpoints than the one the frame entered through.
1 parent fbb668a commit 1f57bb7

File tree

7 files changed

+90
-21
lines changed

7 files changed

+90
-21
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
@@ -999,7 +999,7 @@ const MACAddress_t xMDNS_MacAddressIPv6 = { { 0x33, 0x33, 0x00, 0x00, 0x00, 0xFB
999999
configASSERT( ucIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT );
10001000
ulIPAddress = pxEndPoint->ipv4_settings.ulDNSServerAddresses[ ucIndex ];
10011001

1002-
if( ( ulIPAddress != 0U ) && ( ulIPAddress != ipBROADCAST_IP_ADDRESS ) )
1002+
if( ( ulIPAddress != 0U ) && ( ulIPAddress != FREERTOS_INADDR_BROADCAST ) )
10031003
{
10041004
pxAddress->sin_family = FREERTOS_AF_INET;
10051005
pxAddress->sin_len = ( uint8_t ) sizeof( struct freertos_sockaddr );

source/FreeRTOS_IPv4.c

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,66 @@ 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+
uint32_t ulEndPointBroadcast;
228+
NetworkEndPoint_t * pxEndPoint;
229+
230+
/* Assign a default answer based on the "global" broadcast. This way
231+
* we can still return the correct result even if there are no endpoints. */
232+
xIsBroadcast = ( ulIPAddress == FREERTOS_INADDR_BROADCAST ) ? pdTRUE : pdFALSE;
233+
234+
for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL );
235+
pxEndPoint != NULL;
236+
pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) )
237+
{
238+
#if ( ipconfigUSE_IPv6 == ipconfigENABLE )
239+
/* Skip over any IPv6 endpoints. */
240+
if( pxEndPoint->bits.bIPv6 == pdTRUE )
241+
{
242+
continue;
243+
}
244+
#endif /* ( ipconfigUSE_IPv6 == ipconfigENABLE ) */
245+
246+
/* If we already know if ulIPAddress is a broadcast,
247+
* simply return this first matching IPv4 endpoint. */
248+
if( xIsBroadcast == pdTRUE )
249+
{
250+
break;
251+
}
252+
else if( ulIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress )
253+
{
254+
xIsBroadcast = pdTRUE;
255+
break;
256+
}
257+
}
258+
259+
/* If the caller wants to know the corresponding endpoint, copy the result.
260+
* Note that this may be null if ulIPAddress is 255.255.255.255 AND there are
261+
* no IPv4 endpoints.
262+
* Also, when ulIPAddress is 255.255.255.255, we will
263+
* return the first IPv4 endpoint that we run across. */
264+
if( xIsBroadcast && ( ppxEndPoint != NULL ) )
265+
{
266+
*ppxEndPoint = pxEndPoint;
267+
}
268+
269+
return xIsBroadcast;
270+
}
271+
/*-----------------------------------------------------------*/
272+
213273
/**
214274
* @brief Check if the packet is an illegal loopback packet.
215275
*
@@ -284,9 +344,11 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
284344
{
285345
/* In systems with a very small amount of RAM, it might be advantageous
286346
* to have incoming messages checked earlier, by the network card driver.
287-
* This method may decrease the usage of sparse network buffers. */
347+
* This method may decrease the usage of scarce network buffers. */
288348
uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
289349
uint32_t ulSourceIPAddress = pxIPHeader->ulSourceIPAddress;
350+
/* Get a reference to the endpoint that the packet was assigned to during pxEasyFit() */
351+
NetworkEndPoint_t * pxEndPoint = pxNetworkBuffer->pxEndPoint;
290352

291353
/* Ensure that the incoming packet is not fragmented because the stack
292354
* doesn't not support IP fragmentation. All but the last fragment coming in will have their
@@ -318,16 +380,20 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
318380
}
319381
}
320382
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 ) &&
383+
/* Not destined for the assigned endpoint IPv4 address? */
384+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulIPAddress ) &&
385+
/* Also not an IPv4 broadcast address ? */
386+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) &&
387+
( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) &&
388+
/* And not an IPv4 multicast address ? */
324389
( xIsIPv4Multicast( ulDestinationIPAddress ) == pdFALSE ) )
325390
{
326391
/* Packet is not for this node, release it */
327392
eReturn = eReleaseBuffer;
328393
}
329394
/* Is the source address correct? */
330-
else if( ( FreeRTOS_ntohl( ulSourceIPAddress ) & 0xffU ) == 0xffU )
395+
else if( ( ulSourceIPAddress == pxEndPoint->ipv4_settings.ulBroadcastAddress ) ||
396+
( ulSourceIPAddress == FREERTOS_INADDR_BROADCAST ) )
331397
{
332398
/* The source address cannot be broadcast address. Replying to this
333399
* packet may cause network storms. Drop the packet. */
@@ -336,7 +402,7 @@ enum eFrameProcessingResult prvAllowIPPacketIPv4( const struct xIP_PACKET * cons
336402
else if( ( memcmp( xBroadcastMACAddress.ucBytes,
337403
pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes,
338404
sizeof( MACAddress_t ) ) == 0 ) &&
339-
( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) )
405+
( ulDestinationIPAddress != pxEndPoint->ipv4_settings.ulBroadcastAddress ) && ( ulDestinationIPAddress != FREERTOS_INADDR_BROADCAST ) )
340406
{
341407
/* Ethernet address is a broadcast address, but the IP address is not a
342408
* 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

0 commit comments

Comments
 (0)