summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c1408
1 files changed, 957 insertions, 451 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
index 707c99dc6..bfd2a9c15 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
@@ -40,7 +40,6 @@
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_UDP_IP.h"
-#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
@@ -50,43 +49,52 @@
/* Used to ensure the structure packing is having the desired effect. The
'volatile' is used to prevent compiler warnings about comparing a constant with
a constant. */
-#define ipEXPECTED_EthernetHeader_t_SIZE ( ( size_t ) 14 )
-#define ipEXPECTED_ARPHeader_t_SIZE ( ( size_t ) 28 )
-#define ipEXPECTED_IPHeader_t_SIZE ( ( size_t ) 20 )
-#define ipEXPECTED_IGMPHeader__SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_ICMPHeader_t_SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_UDPHeader_t_SIZE ( ( size_t ) 8 )
-#define ipEXPECTED_TCPHeader_t_SIZE ( ( size_t ) 20 )
-
+#ifndef _lint
+ #define ipEXPECTED_EthernetHeader_t_SIZE ( ( size_t ) 14 )
+ #define ipEXPECTED_ARPHeader_t_SIZE ( ( size_t ) 28 )
+ #define ipEXPECTED_IPHeader_t_SIZE ( ( size_t ) 20 )
+ #define ipEXPECTED_IGMPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_ICMPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_UDPHeader_t_SIZE ( ( size_t ) 8 )
+ #define ipEXPECTED_TCPHeader_t_SIZE ( ( size_t ) 20 )
+#endif
/* ICMP protocol definitions. */
#define ipICMP_ECHO_REQUEST ( ( uint8_t ) 8 )
#define ipICMP_ECHO_REPLY ( ( uint8_t ) 0 )
+/* IPv4 multi-cast addresses range from 224.0.0.0.0 to 240.0.0.0. */
+#define ipFIRST_MULTI_CAST_IPv4 0xE0000000UL
+#define ipLAST_MULTI_CAST_IPv4 0xF0000000UL
+/* The first byte in the IPv4 header combines the IP version (4) with
+with the length of the IP header. */
+#define ipIPV4_VERSION_HEADER_LENGTH_MIN 0x45U
+#define ipIPV4_VERSION_HEADER_LENGTH_MAX 0x4FU
+
/* Time delay between repeated attempts to initialise the network hardware. */
#ifndef ipINITIALISATION_RETRY_DELAY
- #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000 ) )
+ #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000U ) )
#endif
/* Defines how often the ARP timer callback function is executed. The time is
shorted in the Windows simulator as simulated time is not real time. */
#ifndef ipARP_TIMER_PERIOD_MS
#ifdef _WINDOWS_
- #define ipARP_TIMER_PERIOD_MS ( 500 ) /* For windows simulator builds. */
+ #define ipARP_TIMER_PERIOD_MS ( 500U ) /* For windows simulator builds. */
#else
- #define ipARP_TIMER_PERIOD_MS ( 10000 )
+ #define ipARP_TIMER_PERIOD_MS ( 10000U )
#endif
#endif
#ifndef iptraceIP_TASK_STARTING
- #define iptraceIP_TASK_STARTING() do {} while( 0 )
+ #define iptraceIP_TASK_STARTING() do {} while( ipFALSE_BOOL )
#endif
#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
/* When initialising the TCP timer,
give it an initial time-out of 1 second. */
- #define ipTCP_TIMER_PERIOD_MS ( 1000 )
+ #define ipTCP_TIMER_PERIOD_MS ( 1000U )
#endif
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
@@ -102,17 +110,15 @@ needs to call eConsiderFrameForProcessing. */
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#endif
-/* The character used to fill ICMP echo requests, and therefore also the
-character expected to fill ICMP echo replies. */
-#define ipECHO_DATA_FILL_BYTE 'x'
-
-#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
- /* The bits in the two byte IP header field that make up the fragment offset value. */
- #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f )
-#else
- /* The bits in the two byte IP header field that make up the fragment offset value. */
- #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff )
-#endif /* ipconfigBYTE_ORDER */
+#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )
+ #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
+ /* The bits in the two byte IP header field that make up the fragment offset value. */
+ #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f )
+ #else
+ /* The bits in the two byte IP header field that make up the fragment offset value. */
+ #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff )
+ #endif /* ipconfigBYTE_ORDER */
+#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
/* The maximum time the IP task is allowed to remain in the Blocked state if no
events are posted to the network event queue. */
@@ -120,39 +126,22 @@ events are posted to the network event queue. */
#define ipconfigMAX_IP_TASK_SLEEP_TIME ( pdMS_TO_TICKS( 10000UL ) )
#endif
-/* When a new TCP connection is established, the value of
-'ulNextInitialSequenceNumber' will be used as the initial sequence number. It
-is very important that at start-up, 'ulNextInitialSequenceNumber' contains a
-random value. Also its value must be increased continuously in time, to prevent
-a third party guessing the next sequence number and take-over a TCP connection.
-It is advised to increment it by 1 ever 4us, which makes about 256 times
-per ms: */
-#define ipINITIAL_SEQUENCE_NUMBER_FACTOR 256UL
-
/* Returned as the (invalid) checksum when the protocol being checked is not
handled. The value is chosen simply to be easy to spot when debugging. */
-#define ipUNHANDLED_PROTOCOL 0x4321u
+#define ipUNHANDLED_PROTOCOL 0x4321U
-/* Returned to indicate a valid checksum when the checksum does not need to be
-calculated. */
-#define ipCORRECT_CRC 0xffffu
+/* Returned to indicate a valid checksum. */
+#define ipCORRECT_CRC 0xffffU
+
+/* Returned to indicate incorrect checksum. */
+#define ipWRONG_CRC 0x0000U
/* Returned as the (invalid) checksum when the length of the data being checked
had an invalid length. */
-#define ipINVALID_LENGTH 0x1234u
+#define ipINVALID_LENGTH 0x1234U
/*-----------------------------------------------------------*/
-typedef struct xIP_TIMER
-{
- uint32_t
- bActive : 1, /* This timer is running and must be processed. */
- bExpired : 1; /* Timer has expired and a task must be processed. */
- TimeOut_t xTimeOut;
- TickType_t ulRemainingTime;
- TickType_t ulReloadTime;
-} IPTimer_t;
-
/* Used in checksum calculation. */
typedef union _xUnion32
{
@@ -186,7 +175,7 @@ static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetwor
/*
* Process incoming IP packets.
*/
-static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );
+static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/*
@@ -241,8 +230,16 @@ static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime );
static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer );
static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime );
+/* The function 'prvAllowIPPacket()' checks if a packets should be processed. */
static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
- NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength );
+ const NetworkBufferDescriptor_t * const pxNetworkBuffer,
+ UBaseType_t uxHeaderLength );
+
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
+ /* Even when the driver takes care of checksum calculations,
+ the IP-task will still check if the length fields are OK. */
+ static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength );
+#endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
/*-----------------------------------------------------------*/
@@ -261,12 +258,14 @@ NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 };
/* Default values for the above struct in case DHCP
does not lead to a confirmed request. */
+/* coverity[misra_c_2012_rule_8_9_violation] */
+/* "xDefaultAddressing" should be defined at block scope. */
NetworkAddressingParameters_t xDefaultAddressing = { 0, 0, 0, 0, 0 };
/* Used to ensure network down events cannot be missed when they cannot be
posted to the network event queue because the network event queue is already
full. */
-static BaseType_t xNetworkDownEventPending = pdFALSE;
+static volatile BaseType_t xNetworkDownEventPending = pdFALSE;
/* Stores the handle of the task that handles the stack. The handle is used
(indirectly) by some utility function to determine if the utility function is
@@ -304,6 +303,8 @@ static IPTimer_t xARPTimer;
#endif
/* Set to pdTRUE when the IP task is ready to start processing packets. */
+/* coverity[misra_c_2012_rule_8_9_violation] */
+/* "xIPTaskInitialised" should be defined at block scope. */
static BaseType_t xIPTaskInitialised = pdFALSE;
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
@@ -313,6 +314,8 @@ static BaseType_t xIPTaskInitialised = pdFALSE;
/*-----------------------------------------------------------*/
+/* Coverity want to make pvParameters const, which would make it incompatible. */
+/* coverity[misra_c_2012_rule_8_13_violation] */
static void prvIPTask( void *pvParameters )
{
IPStackEvent_t xReceivedEvent;
@@ -359,7 +362,7 @@ struct freertos_sockaddr xAddress;
/* Wait until there is something to do. If the following call exits
* due to a time out rather than a message being received, set a
* 'NoEvent' value. */
- if ( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE )
+ if ( xQueueReceive( xNetworkEventQueue, ipPOINTER_CAST( void *, &xReceivedEvent ), xNextIPSleep ) == pdFALSE )
{
xReceivedEvent.eEventType = eNoEvent;
}
@@ -393,13 +396,13 @@ struct freertos_sockaddr xAddress;
/* The network hardware driver has received a new packet. A
pointer to the received buffer is located in the pvData member
of the received event structure. */
- prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
+ prvHandleEthernetPacket( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ) );
break;
case eNetworkTxEvent:
/* Send a network packet. The ownership will be transferred to
the driver, which will release it after delivery. */
- xNetworkInterfaceOutput( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ), pdTRUE );
+ ( void ) xNetworkInterfaceOutput( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ), pdTRUE );
break;
case eARPTimerEvent :
@@ -413,16 +416,16 @@ struct freertos_sockaddr xAddress;
usLocalPort. vSocketBind() will actually bind the socket and the
API will unblock as soon as the eSOCKET_BOUND event is
triggered. */
- pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
- xAddress.sin_addr = 0u; /* For the moment. */
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData );
+ xAddress.sin_addr = 0U; /* For the moment. */
xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );
- pxSocket->usLocalPort = 0u;
- vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
+ pxSocket->usLocalPort = 0U;
+ ( void ) vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
/* Before 'eSocketBindEvent' was sent it was tested that
( xEventGroup != NULL ) so it can be used now to wake up the
user. */
- pxSocket->xEventBits |= eSOCKET_BOUND;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_BOUND;
vSocketWakeUpUser( pxSocket );
break;
@@ -431,20 +434,21 @@ struct freertos_sockaddr xAddress;
IP-task to actually close a socket. This is handled in
vSocketClose(). As the socket gets closed, there is no way to
report back to the API, so the API won't wait for the result */
- vSocketClose( ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData ) );
+ ( void ) vSocketClose( ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData ) );
break;
case eStackTxEvent :
/* The network stack has generated a packet to send. A
pointer to the generated buffer is located in the pvData
member of the received event structure. */
- vProcessGeneratedUDPPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
+ vProcessGeneratedUDPPacket( ipPOINTER_CAST( NetworkBufferDescriptor_t *, xReceivedEvent.pvData ) );
break;
case eDHCPEvent:
/* The DHCP state machine needs processing. */
#if( ipconfigUSE_DHCP == 1 )
{
+ /* Process DHCP messages for a given end-point. */
vDHCPProcess( pdFALSE );
}
#endif /* ipconfigUSE_DHCP */
@@ -456,7 +460,17 @@ struct freertos_sockaddr xAddress;
and update the socket field xSocketBits. */
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{
- vSocketSelect( ( SocketSelect_t * ) ( xReceivedEvent.pvData ) );
+ #if( ipconfigSELECT_USES_NOTIFY != 0 )
+ {
+ SocketSelectMessage_t *pxMessage = ipPOINTER_CAST( SocketSelectMessage_t *, xReceivedEvent.pvData );
+ vSocketSelect( pxMessage->pxSocketSet );
+ ( void ) xTaskNotifyGive( pxMessage->xTaskhandle );
+ }
+ #else
+ {
+ vSocketSelect( ipPOINTER_CAST( SocketSelect_t *, xReceivedEvent.pvData ) );
+ }
+ #endif /* ( ipconfigSELECT_USES_NOTIFY != 0 ) */
}
#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
break;
@@ -466,7 +480,7 @@ struct freertos_sockaddr xAddress;
{
/* Some task wants to signal the user of this socket in
order to interrupt a call to recv() or a call to select(). */
- FreeRTOS_SignalSocket( ( Socket_t ) xReceivedEvent.pvData );
+ ( void ) FreeRTOS_SignalSocket( ipPOINTER_CAST( Socket_t, xReceivedEvent.pvData ) );
}
#endif /* ipconfigSUPPORT_SIGNALS */
break;
@@ -487,11 +501,11 @@ struct freertos_sockaddr xAddress;
received a new connection. */
#if( ipconfigUSE_TCP == 1 )
{
- pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
+ pxSocket = ipPOINTER_CAST( FreeRTOS_Socket_t *, xReceivedEvent.pvData );
if( xTCPCheckNewClient( pxSocket ) != pdFALSE )
{
- pxSocket->xEventBits |= eSOCKET_ACCEPT;
+ pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT;
vSocketWakeUpUser( pxSocket );
}
}
@@ -508,6 +522,10 @@ struct freertos_sockaddr xAddress;
#endif /* ipconfigUSE_TCP */
break;
+ case eNoEvent:
+ /* xQueueReceive() returned because of a normal time-out. */
+ break;
+
default :
/* Should not get here. */
break;
@@ -516,8 +534,10 @@ struct freertos_sockaddr xAddress;
if( xNetworkDownEventPending != pdFALSE )
{
/* A network down event could not be posted to the network event
- queue because the queue was full. Try posting again. */
- FreeRTOS_NetworkDown();
+ queue because the queue was full.
+ As this code runs in the IP-task, it can be done directly by
+ calling prvProcessNetworkDownEvent(). */
+ prvProcessNetworkDownEvent();
}
}
}
@@ -616,7 +636,7 @@ TickType_t xMaximumSleepTime;
#if( ipconfigDNS_USE_CALLBACKS != 0 )
{
- if( xDNSTimer.bActive != pdFALSE )
+ if( xDNSTimer.bActive != pdFALSE_UNSIGNED )
{
if( xDNSTimer.ulRemainingTime < xMaximumSleepTime )
{
@@ -635,7 +655,7 @@ static void prvCheckNetworkTimers( void )
/* Is it time for ARP processing? */
if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
{
- xSendEventToIPTask( eARPTimerEvent );
+ ( void ) xSendEventToIPTask( eARPTimerEvent );
}
#if( ipconfigUSE_DHCP == 1 )
@@ -643,15 +663,13 @@ static void prvCheckNetworkTimers( void )
/* Is it time for DHCP processing? */
if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )
{
- xSendEventToIPTask( eDHCPEvent );
+ ( void ) xSendEventToIPTask( eDHCPEvent );
}
}
#endif /* ipconfigUSE_DHCP */
#if( ipconfigDNS_USE_CALLBACKS != 0 )
{
- extern void vDNSCheckCallBack( void *pvSearchID );
-
/* Is it time for DNS processing? */
if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
{
@@ -666,7 +684,9 @@ static void prvCheckNetworkTimers( void )
TickType_t xNextTime;
BaseType_t xCheckTCPSockets;
- if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0u )
+ /* If the IP task has messages waiting to be processed then
+ it will not sleep in any case. */
+ if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
{
xWillSleep = pdTRUE;
}
@@ -736,8 +756,14 @@ BaseType_t xReturn;
{
/* The timer might have set the bExpired flag already, if not, check the
value of xTimeOut against ulRemainingTime. */
- if( ( pxTimer->bExpired != pdFALSE_UNSIGNED ) ||
- ( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE ) )
+ if( pxTimer->bExpired == pdFALSE_UNSIGNED )
+ {
+ if( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE )
+ {
+ pxTimer->bExpired = pdTRUE_UNSIGNED;
+ }
+ }
+ if( pxTimer->bExpired != pdFALSE_UNSIGNED )
{
prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
xReturn = pdTRUE;
@@ -772,7 +798,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
iptraceNETWORK_DOWN();
}
/*-----------------------------------------------------------*/
-
+/* Utility function. Process Network Down event from ISR. */
BaseType_t FreeRTOS_NetworkDownFromISR( void )
{
static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
@@ -794,29 +820,29 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
}
/*-----------------------------------------------------------*/
-void *FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
+void *FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes, TickType_t uxBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
void *pvReturn;
+TickType_t uxBlockTime = uxBlockTimeTicks;
/* Cap the block time. The reason for this is explained where
ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined (assuming an official
FreeRTOSIPConfig.h header file is being used). */
- if( xBlockTimeTicks > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
+ if( uxBlockTime > ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ) )
{
- xBlockTimeTicks = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
+ uxBlockTime = ( ( TickType_t ) ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS );
}
/* Obtain a network buffer with the required amount of storage. */
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + xRequestedSizeBytes, xBlockTimeTicks );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + uxRequestedSizeBytes, uxBlockTime );
if( pxNetworkBuffer != NULL )
{
/* Set the actual packet size in case a bigger buffer was returned. */
- pxNetworkBuffer->xDataLength = sizeof( UDPPacket_t ) + xRequestedSizeBytes;
-
- /* Leave space for the UPD header. */
- pvReturn = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
+ pxNetworkBuffer->xDataLength = sizeof( UDPPacket_t ) + uxRequestedSizeBytes;
+ /* Skip 3 headers. */
+ pvReturn = &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( UDPPacket_t ) ] );
}
else
{
@@ -827,7 +853,7 @@ void *pvReturn;
}
/*-----------------------------------------------------------*/
-NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
+NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer,
size_t uxNewLength )
{
NetworkBufferDescriptor_t * pxNewBuffer;
@@ -847,7 +873,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
pxNewBuffer->ulIPAddress = pxNetworkBuffer->ulIPAddress;
pxNewBuffer->usPort = pxNetworkBuffer->usPort;
pxNewBuffer->usBoundPort = pxNetworkBuffer->usBoundPort;
- memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
+ ( void ) memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
}
return pxNewBuffer;
@@ -858,7 +884,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer )
{
- uint8_t *pucBuffer;
+ const uint8_t *pucBuffer;
NetworkBufferDescriptor_t *pxResult;
if( pvBuffer == NULL )
@@ -868,7 +894,7 @@ NetworkBufferDescriptor_t * pxNewBuffer;
else
{
/* Obtain the network buffer from the zero copy pointer. */
- pucBuffer = ( uint8_t * ) pvBuffer;
+ pucBuffer = ipPOINTER_CAST( const uint8_t *, pvBuffer );
/* The input here is a pointer to a payload buffer. Subtract the
size of the header in the network buffer, usually 8 + 2 bytes. */
@@ -876,9 +902,9 @@ NetworkBufferDescriptor_t * pxNewBuffer;
/* Here a pointer was placed to the network descriptor. As a
pointer is dereferenced, make sure it is well aligned. */
- if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - ( size_t ) 1 ) ) == ( uint32_t ) 0 )
+ if( ( ( ( size_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1U ) ) == ( size_t ) 0U )
{
- pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
+ pxResult = * ( ipPOINTER_CAST( NetworkBufferDescriptor_t **, pucBuffer ) );
}
else
{
@@ -892,9 +918,9 @@ NetworkBufferDescriptor_t * pxNewBuffer;
#endif /* ipconfigZERO_COPY_TX_DRIVER != 0 */
/*-----------------------------------------------------------*/
-NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )
+NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( const void * pvBuffer )
{
-uint8_t *pucBuffer;
+const uint8_t *pucBuffer;
NetworkBufferDescriptor_t *pxResult;
if( pvBuffer == NULL )
@@ -904,21 +930,21 @@ NetworkBufferDescriptor_t *pxResult;
else
{
/* Obtain the network buffer from the zero copy pointer. */
- pucBuffer = ( uint8_t * ) pvBuffer;
+ pucBuffer = ipPOINTER_CAST( const uint8_t *, pvBuffer );
/* The input here is a pointer to a payload buffer. Subtract
the total size of a UDP/IP header plus the size of the header in
the network buffer, usually 8 + 2 bytes. */
- pucBuffer -= ( sizeof( UDPPacket_t ) + ipBUFFER_PADDING );
+ pucBuffer -= ( sizeof( UDPPacket_t ) + ( ( size_t ) ipBUFFER_PADDING ) );
/* Here a pointer was placed to the network descriptor,
As a pointer is dereferenced, make sure it is well aligned */
- if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 )
+ if( ( ( ( size_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1U ) ) == 0U )
{
/* The following statement may trigger a:
warning: cast increases required alignment of target type [-Wcast-align].
It has been confirmed though that the alignment is suitable. */
- pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
+ pxResult = * ( ipPOINTER_CAST( NetworkBufferDescriptor_t **, pucBuffer ) );
}
else
{
@@ -930,7 +956,7 @@ NetworkBufferDescriptor_t *pxResult;
}
/*-----------------------------------------------------------*/
-void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer )
+void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer )
{
vReleaseNetworkBufferAndDescriptor( pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer ) );
}
@@ -949,16 +975,21 @@ BaseType_t xReturn = pdFALSE;
configASSERT( xNetworkEventQueue == NULL );
configASSERT( xIPTaskHandle == NULL );
- /* Check structure packing is correct. */
- configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );
- configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );
- configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );
- configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );
- configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );
-
+ #ifndef _lint
+ {
+ /* Check if MTU is big enough. */
+ configASSERT( ( ( size_t ) ipconfigNETWORK_MTU ) >= ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + ipconfigTCP_MSS ) );
+ /* Check structure packing is correct. */
+ configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );
+ configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );
+ configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );
+ configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );
+ configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );
+ }
+ #endif
/* Attempt to create the queue used to communicate with the IP task. */
xNetworkEventQueue = xQueueCreate( ( UBaseType_t ) ipconfigEVENT_QUEUE_LENGTH, ( UBaseType_t ) sizeof( IPStackEvent_t ) );
- configASSERT( xNetworkEventQueue );
+ configASSERT( xNetworkEventQueue != NULL );
if( xNetworkEventQueue != NULL )
{
@@ -980,7 +1011,7 @@ BaseType_t xReturn = pdFALSE;
xNetworkAddressing.ulDNSServerAddress = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );
xNetworkAddressing.ulBroadcastAddress = ( xNetworkAddressing.ulDefaultIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
- memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
+ ( void ) memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
#if ipconfigUSE_DHCP == 1
{
@@ -994,7 +1025,7 @@ BaseType_t xReturn = pdFALSE;
/* Added to prevent ARP flood to gateway. Ensure the
gateway is on the same subnet as the IP address. */
- if( xNetworkAddressing.ulGatewayAddress != 0ul )
+ if( xNetworkAddressing.ulGatewayAddress != 0UL )
{
configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) );
}
@@ -1003,16 +1034,18 @@ BaseType_t xReturn = pdFALSE;
/* The MAC address is stored in the start of the default packet
header fragment, which is used when sending UDP packets. */
- memcpy( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
/* Prepare the sockets interface. */
- xReturn = vNetworkSocketsInit();
-
- if( pdTRUE == xReturn )
- {
- /* Create the task that processes Ethernet and stack events. */
- xReturn = xTaskCreate( prvIPTask, "IP-task", ( uint16_t )ipconfigIP_TASK_STACK_SIZE_WORDS, NULL, ( UBaseType_t )ipconfigIP_TASK_PRIORITY, &xIPTaskHandle );
- }
+ vNetworkSocketsInit();
+
+ /* Create the task that processes Ethernet and stack events. */
+ xReturn = xTaskCreate( prvIPTask,
+ "IP-task",
+ ( uint16_t )ipconfigIP_TASK_STACK_SIZE_WORDS,
+ NULL,
+ ( UBaseType_t )ipconfigIP_TASK_PRIORITY,
+ &( xIPTaskHandle ) );
}
else
{
@@ -1032,7 +1065,10 @@ BaseType_t xReturn = pdFALSE;
}
/*-----------------------------------------------------------*/
-void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress )
+void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress,
+ uint32_t *pulNetMask,
+ uint32_t *pulGatewayAddress,
+ uint32_t *pulDNSServerAddress )
{
/* Return the address configuration to the caller. */
@@ -1058,7 +1094,10 @@ void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetM
}
/*-----------------------------------------------------------*/
-void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress )
+void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress,
+ const uint32_t *pulNetMask,
+ const uint32_t *pulGatewayAddress,
+ const uint32_t *pulDNSServerAddress )
{
/* Update the address configuration. */
@@ -1086,22 +1125,39 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
- BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks )
+ BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t uxNumberOfBytesToSend, TickType_t uxBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
ICMPHeader_t *pxICMPHeader;
+ EthernetHeader_t *pxEthernetHeader;
BaseType_t xReturn = pdFAIL;
static uint16_t usSequenceNumber = 0;
uint8_t *pucChar;
+ size_t uxTotalLength;
IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
- if( (xNumberOfBytesToSend >= 1 ) && ( xNumberOfBytesToSend < ( ( ipconfigNETWORK_MTU - sizeof( IPHeader_t ) ) - sizeof( ICMPHeader_t ) ) ) && ( uxGetNumberOfFreeNetworkBuffers() >= 3 ) )
+ uxTotalLength = uxNumberOfBytesToSend + sizeof( ICMPPacket_t );
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxTotalLength, uxBlockTimeTicks );
+
+ if( pxNetworkBuffer != NULL )
{
- pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xNumberOfBytesToSend + sizeof( ICMPPacket_t ), xBlockTimeTicks );
+ BaseType_t xEnoughSpace;
- if( pxNetworkBuffer != NULL )
+ if( uxNumberOfBytesToSend < ( ipconfigNETWORK_MTU - ( sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) ) ) )
+ {
+ xEnoughSpace = pdTRUE;
+ }
+ else
+ {
+ xEnoughSpace = pdFALSE;
+ }
+ if( ( uxGetNumberOfFreeNetworkBuffers() >= 3U ) && ( uxNumberOfBytesToSend >= 1U ) && ( xEnoughSpace != pdFALSE ) )
{
- pxICMPHeader = ( ICMPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] );
+ pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
+ pxEthernetHeader->usFrameType = ipIPv4_FRAME_TYPE;
+
+
+ pxICMPHeader = ipPOINTER_CAST( ICMPHeader_t *, &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] ) );
usSequenceNumber++;
/* Fill in the basic header information. */
@@ -1112,10 +1168,10 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
/* Find the start of the data. */
pucChar = ( uint8_t * ) pxICMPHeader;
- pucChar += sizeof( ICMPHeader_t );
+ pucChar = &(pucChar[ sizeof( ICMPHeader_t ) ] );
/* Just memset the data to a fixed value. */
- memset( ( void * ) pucChar, ( int ) ipECHO_DATA_FILL_BYTE, xNumberOfBytesToSend );
+ ( void ) memset( pucChar, ( int ) ipECHO_DATA_FILL_BYTE, uxNumberOfBytesToSend );
/* The message is complete, IP and checksum's are handled by
vProcessGeneratedUDPPacket */
@@ -1123,19 +1179,19 @@ void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint3
pxNetworkBuffer->ulIPAddress = ulIPAddress;
pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA;
/* xDataLength is the size of the total packet, including the Ethernet header. */
- pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPPacket_t );
+ pxNetworkBuffer->xDataLength = uxTotalLength;
/* Send to the stack. */
xStackTxEvent.pvData = pxNetworkBuffer;
- if( xSendEventStructToIPTask( &xStackTxEvent, xBlockTimeTicks) != pdPASS )
+ if( xSendEventStructToIPTask( &( xStackTxEvent ), uxBlockTimeTicks ) != pdPASS )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
}
else
{
- xReturn = usSequenceNumber;
+ xReturn = ( BaseType_t ) usSequenceNumber;
}
}
}
@@ -1163,9 +1219,10 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
}
/*-----------------------------------------------------------*/
-BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout )
+BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t uxTimeout )
{
BaseType_t xReturn, xSendMessage;
+TickType_t uxUseTimeout = uxTimeout;
if( ( xIPIsNetworkTaskReady() == pdFALSE ) && ( pxEvent->eEventType != eNetworkDownEvent ) )
{
@@ -1186,7 +1243,7 @@ BaseType_t xReturn, xSendMessage;
IP task is already awake processing other message. */
xTCPTimer.bExpired = pdTRUE_UNSIGNED;
- if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0u )
+ if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U )
{
/* Not actually going to send the message but this is not a
failure as the message didn't need to be sent. */
@@ -1200,12 +1257,12 @@ BaseType_t xReturn, xSendMessage;
{
/* The IP task cannot block itself while waiting for itself to
respond. */
- if( ( xIsCallingFromIPTask() == pdTRUE ) && ( xTimeout > ( TickType_t ) 0 ) )
+ if( ( xIsCallingFromIPTask() == pdTRUE ) && ( uxUseTimeout > ( TickType_t ) 0U ) )
{
- xTimeout = ( TickType_t ) 0;
+ uxUseTimeout = ( TickType_t ) 0;
}
- xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, xTimeout );
+ xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout );
if( xReturn == pdFAIL )
{
@@ -1231,21 +1288,22 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
eFrameProcessingResult_t eReturn;
const EthernetHeader_t *pxEthernetHeader;
- pxEthernetHeader = ( const EthernetHeader_t * ) pucEthernetBuffer;
+ /* Map the buffer onto Ethernet Header struct for easy access to fields. */
+ pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
- if( memcmp( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) &( pxEthernetHeader->xDestinationAddress ), sizeof( MACAddress_t ) ) == 0 )
+ if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
- /* The packet was directed to this node directly - process it. */
+ /* The packet was directed to this node - process it. */
eReturn = eProcessBuffer;
}
- else if( memcmp( ( void * ) xBroadcastMACAddress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
+ else if( memcmp( xBroadcastMACAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
/* The packet was a broadcast - process it. */
eReturn = eProcessBuffer;
}
else
#if( ipconfigUSE_LLMNR == 1 )
- if( memcmp( ( void * ) xLLMNR_MacAdress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
+ if( memcmp( xLLMNR_MacAdress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
/* The packet is a request for LLMNR - process it. */
eReturn = eProcessBuffer;
@@ -1323,7 +1381,7 @@ static void prvProcessNetworkDownEvent( void )
{
/* The network is not up until DHCP has completed. */
vDHCPProcess( pdTRUE );
- xSendEventToIPTask( eDHCPEvent );
+ ( void ) xSendEventToIPTask( eDHCPEvent );
}
#else
{
@@ -1361,18 +1419,23 @@ void vIPNetworkUpCalls( void )
static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
-EthernetHeader_t *pxEthernetHeader;
+const EthernetHeader_t *pxEthernetHeader;
eFrameProcessingResult_t eReturned = eReleaseBuffer;
- configASSERT( pxNetworkBuffer );
+ configASSERT( pxNetworkBuffer != NULL );
/* Interpret the Ethernet frame. */
if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
{
eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
- pxEthernetHeader = ( EthernetHeader_t * )( pxNetworkBuffer->pucEthernetBuffer );
+ /* Map the buffer onto the Ethernet Header struct for easy access to the fields. */
+ pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
+
+ /* The condition "eReturned == eProcessBuffer" must be true. */
+ #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
if( eReturned == eProcessBuffer )
+ #endif
{
/* Interpret the received Ethernet packet. */
switch( pxEthernetHeader->usFrameType )
@@ -1381,7 +1444,7 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
/* The Ethernet frame contains an ARP packet. */
if( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) )
{
- eReturned = eARPProcessPacket( ( ARPPacket_t * )pxNetworkBuffer->pucEthernetBuffer );
+ eReturned = eARPProcessPacket( ipPOINTER_CAST( ARPPacket_t *, pxNetworkBuffer->pucEthernetBuffer ) );
}
else
{
@@ -1393,7 +1456,7 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
/* The Ethernet frame contains an IP packet. */
if( pxNetworkBuffer->xDataLength >= sizeof( IPPacket_t ) )
{
- eReturned = prvProcessIPPacket( ( IPPacket_t * )pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer );
+ eReturned = prvProcessIPPacket( ipPOINTER_CAST( IPPacket_t *, pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer );
}
else
{
@@ -1426,6 +1489,8 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
yet. */
break;
+ case eReleaseBuffer :
+ case eProcessBuffer :
default :
/* The frame is not being used anywhere, and the
NetworkBufferDescriptor_t structure containing the frame should
@@ -1436,8 +1501,38 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
}
/*-----------------------------------------------------------*/
+BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress )
+{
+BaseType_t xReturn;
+uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress );
+
+ if( ( ulIP >= ipFIRST_MULTI_CAST_IPv4 ) && ( ulIP < ipLAST_MULTI_CAST_IPv4 ) )
+ {
+ xReturn = pdTRUE;
+ }
+ else
+ {
+ xReturn = pdFALSE;
+ }
+ return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress, MACAddress_t *pxMACAddress )
+{
+uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress );
+
+ pxMACAddress->ucBytes[ 0 ] = ( uint8_t ) 0x01U;
+ pxMACAddress->ucBytes[ 1 ] = ( uint8_t ) 0x00U;
+ pxMACAddress->ucBytes[ 2 ] = ( uint8_t ) 0x5EU;
+ pxMACAddress->ucBytes[ 3 ] = ( uint8_t ) ( ( ulIP >> 16 ) & 0x7fU ); /* Use 7 bits. */
+ pxMACAddress->ucBytes[ 4 ] = ( uint8_t ) ( ( ulIP >> 8 ) & 0xffU ); /* Use 8 bits. */
+ pxMACAddress->ucBytes[ 5 ] = ( uint8_t ) ( ( ulIP ) & 0xffU ); /* Use 8 bits. */
+}
+/*-----------------------------------------------------------*/
+
static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
- NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )
+ const NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )
{
eFrameProcessingResult_t eReturn = eProcessBuffer;
@@ -1464,9 +1559,10 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Can not handle, fragmented packet. */
eReturn = eReleaseBuffer;
}
- /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
- * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
- else if( ( pxIPHeader->ucVersionHeaderLength < 0x45u ) || ( pxIPHeader->ucVersionHeaderLength > 0x4Fu ) )
+ /* Test if the length of the IP-header is between 20 and 60 bytes,
+ and if the IP-version is 4. */
+ else if( ( pxIPHeader->ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
+ ( pxIPHeader->ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
{
/* Can not handle, unknown or invalid header version. */
eReturn = eReleaseBuffer;
@@ -1487,6 +1583,10 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Packet is not for this node, release it */
eReturn = eReleaseBuffer;
}
+ else
+ {
+ /* Packet is not fragemented, destination is this device. */
+ }
}
#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
@@ -1498,7 +1598,7 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
{
/* Is the IP header checksum correct? */
if( ( pxIPHeader->ucProtocol != ( uint8_t ) ipPROTOCOL_ICMP ) &&
- ( usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )
+ ( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )
{
/* Check sum in IP-header not correct. */
eReturn = eReleaseBuffer;
@@ -1509,12 +1609,66 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
/* Protocol checksum not accepted. */
eReturn = eReleaseBuffer;
}
+ else
+ {
+ /* The checksum of the received packet is OK. */
+ }
}
}
#else
{
+
+ if (eReturn == eProcessBuffer )
+ {
+ if( xCheckSizeFields( ( uint8_t * )( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength ) != pdPASS )
+ {
+ /* Some of the length checks were not successful. */
+ eReturn = eReleaseBuffer;
+ }
+ }
+
+ #if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
+ {
+ /* Check if this is a UDP packet without a checksum. */
+ if (eReturn == eProcessBuffer )
+ {
+ /* ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is defined as 0,
+ and so UDP packets carrying a protocol checksum of 0, will
+ be dropped. */
+
+ /* Identify the next protocol. */
+ if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ ProtocolPacket_t *pxProtPack;
+ const uint16_t *pusChecksum;
+
+ /* pxProtPack will point to the offset were the protocols begin. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+ pusChecksum = ( const uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
+ if( *pusChecksum == ( uint16_t ) 0U )
+ {
+ #if( ipconfigHAS_PRINTF != 0 )
+ {
+ static BaseType_t xCount = 0;
+
+ if( xCount < 5 )
+ {
+ FreeRTOS_printf( ( "prvAllowIPPacket: UDP packet from %xip without CRC dropped\n",
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
+ xCount++;
+ }
+ }
+ #endif /* ( ipconfigHAS_PRINTF != 0 ) */
+
+ /* Protocol checksum not accepted. */
+ eReturn = eReleaseBuffer;
+ }
+ }
+ }
+ }
+ #endif /* ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 ) */
+
/* to avoid warning unused parameters */
- ( void ) pxNetworkBuffer;
( void ) uxHeaderLength;
}
#endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */
@@ -1523,11 +1677,12 @@ eFrameProcessingResult_t eReturn = eProcessBuffer;
}
/*-----------------------------------------------------------*/
-static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )
+static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
eFrameProcessingResult_t eReturn;
IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
-UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( pxIPHeader->ucVersionHeaderLength & 0x0Fu ) << 2 );
+size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
+UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( uxLength & 0x0FU ) << 2 );
uint8_t ucProtocol;
/* Bound the calculated header length: take away the Ethernet header size,
@@ -1536,142 +1691,166 @@ uint8_t ucProtocol;
if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
{
- return eReleaseBuffer;
+ eReturn = eReleaseBuffer;
}
-
- ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
- /* Check if the IP headers are acceptable and if it has our destination. */
- eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
-
- if( eReturn == eProcessBuffer )
+ else
{
- if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
- {
- /* All structs of headers expect a IP header size of 20 bytes
- * IP header options were included, we'll ignore them and cut them out
- * Note: IP options are mostly use in Multi-cast protocols */
- const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
- /* From: the previous start of UDP/ICMP/TCP data */
- uint8_t *pucSource = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + uxHeaderLength);
- /* To: the usual start of UDP/ICMP/TCP data at offset 20 from IP header */
- uint8_t *pucTarget = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER);
- /* How many: total length minus the options and the lower headers */
- const size_t xMoveLen = pxNetworkBuffer->xDataLength - optlen - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_ETH_HEADER;
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+ /* Check if the IP headers are acceptable and if it has our destination. */
+ eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
- memmove( pucTarget, pucSource, xMoveLen );
- pxNetworkBuffer->xDataLength -= optlen;
-
- /* Fix-up new version/header length field in IP packet. */
- pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0 ) | /* High nibble is the version. */
- ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0F ); /* Low nibble is the header size, in bytes, divided by four. */
- }
-
- /* Add the IP and MAC addresses to the ARP table if they are not
- already there - otherwise refresh the age of the existing
- entry. */
- if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
- {
- /* Refresh the ARP cache with the IP/MAC-address of the received packet
- * For UDP packets, this will be done later in xProcessReceivedUDPPacket()
- * as soon as know that the message will be handled by someone
- * This will prevent that the ARP cache will get overwritten
- * with the IP-address of useless broadcast packets
- */
- vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
- }
- switch( ucProtocol )
+ if( eReturn == eProcessBuffer )
{
- case ipPROTOCOL_ICMP :
- /* The IP packet contained an ICMP frame. Don't bother
- checking the ICMP checksum, as if it is wrong then the
- wrong data will also be returned, and the source of the
- ping will know something went wrong because it will not
- be able to validate what it receives. */
- #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
+ /* Are there IP-options. */
+ if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
+ {
+ /* The size of the IP-header is larger than 20 bytes.
+ The extra space is used for IP-options. */
+ #if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
{
- if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
- {
- ICMPPacket_t *pxICMPPacket = ( ICMPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer );
- if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
- {
- eReturn = prvProcessICMPPacket( pxICMPPacket );
- }
- }
- else
- {
- eReturn = eReleaseBuffer;
- }
+ /* All structs of headers expect a IP header size of 20 bytes
+ * IP header options were included, we'll ignore them and cut them out. */
+ const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
+ /* From: the previous start of UDP/ICMP/TCP data. */
+ const uint8_t *pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
+ /* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
+ uint8_t *pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
+ /* How many: total length minus the options and the lower headers. */
+ const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
+
+ ( void ) memmove( pucTarget, pucSource, xMoveLen );
+ pxNetworkBuffer->xDataLength -= optlen;
+
+ /* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
+ pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
+ ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
}
- #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
- break;
-
- case ipPROTOCOL_UDP :
+ #else
{
- /* The IP packet contained a UDP frame. */
- UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+ /* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
+ IP-options will be dropped. */
+ eReturn = eReleaseBuffer;
+ }
+ #endif
+ }
- /* Only proceed if the payload length indicated in the header
- appears to be valid. */
- if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) && ( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) >= sizeof( UDPHeader_t ) ) )
- {
- size_t uxPayloadSize_1, uxPayloadSize_2;
- /* The UDP payload size can be calculated by subtracting the
- * header size from `xDataLength`.
- * However, the `xDataLength` may be longer that expected,
- * e.g. when a small packet is padded with zero's.
- * The UDP header contains a field `usLength` reflecting
- * the payload size plus the UDP header ( 8 bytes ).
- * Set `xDataLength` to the size of the headers,
- * plus the lower of the two calculated payload sizes.
- */
-
- uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
- uxPayloadSize_2 = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t );
- if( uxPayloadSize_1 > uxPayloadSize_2 )
+ if( eReturn != eReleaseBuffer )
+ {
+ /* Add the IP and MAC addresses to the ARP table if they are not
+ already there - otherwise refresh the age of the existing
+ entry. */
+ if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ /* Refresh the ARP cache with the IP/MAC-address of the received
+ packet. For UDP packets, this will be done later in
+ xProcessReceivedUDPPacket(), as soon as it's know that the message
+ will be handled. This will prevent the ARP cache getting
+ overwritten with the IP address of useless broadcast packets. */
+ vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
+ }
+ switch( ucProtocol )
+ {
+ case ipPROTOCOL_ICMP :
+ /* The IP packet contained an ICMP frame. Don't bother checking
+ the ICMP checksum, as if it is wrong then the wrong data will
+ also be returned, and the source of the ping will know something
+ went wrong because it will not be able to validate what it
+ receives. */
+ #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
{
- pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
+ if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
+ {
+ /* Map the buffer onto a ICMP-Packet struct to easily access the
+ * fields of ICMP packet. */
+ ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
+ {
+ eReturn = prvProcessICMPPacket( pxICMPPacket );
+ }
+ }
+ else
+ {
+ eReturn = eReleaseBuffer;
+ }
}
+ #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
+ break;
- /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
- pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
- pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
-
- /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
- * In some cases, the upper-layer checksum has been calculated
- * by the NIC driver.
- *
- * Pass the packet payload to the UDP sockets implementation. */
- if( xProcessReceivedUDPPacket( pxNetworkBuffer,
- pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
+ case ipPROTOCOL_UDP :
{
- eReturn = eFrameConsumed;
+ /* The IP packet contained a UDP frame. */
+
+ /* Map the buffer onto a UDP-Packet struct to easily access the
+ * fields of UDP packet. */
+ const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
+ uint16_t usLength;
+
+ /* Note the header values required prior to the checksum
+ generation as the checksum pseudo header may clobber some of
+ these values. */
+ usLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength );
+ if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) &&
+ ( ( ( size_t ) usLength ) >= sizeof( UDPHeader_t ) ) )
+ {
+ size_t uxPayloadSize_1, uxPayloadSize_2;
+ /* Ensure that downstream UDP packet handling has the lesser
+ of: the actual network buffer Ethernet frame length, or
+ the sender's UDP packet header payload length, minus the
+ size of the UDP header.
+
+ The size of the UDP packet structure in this implementation
+ includes the size of the Ethernet header, the size of
+ the IP header, and the size of the UDP header. */
+ uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
+ uxPayloadSize_2 = ( ( size_t ) usLength ) - sizeof( UDPHeader_t );
+ if( uxPayloadSize_1 > uxPayloadSize_2 )
+ {
+ pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
+ }
+
+ /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
+ pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
+ pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
+
+ /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
+ In some cases, the upper-layer checksum has been calculated
+ by the NIC driver. */
+
+ /* Pass the packet payload to the UDP sockets
+ implementation. */
+ if( xProcessReceivedUDPPacket( pxNetworkBuffer,
+ pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
+ {
+ eReturn = eFrameConsumed;
+ }
+ }
+ else
+ {
+ eReturn = eReleaseBuffer;
+ }
}
- }
- else
- {
- eReturn = eReleaseBuffer;
- }
- }
- break;
+ break;
#if ipconfigUSE_TCP == 1
- case ipPROTOCOL_TCP :
- {
+ case ipPROTOCOL_TCP :
+ {
- if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
- {
- eReturn = eFrameConsumed;
- }
+ if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
+ {
+ eReturn = eFrameConsumed;
+ }
- /* Setting this variable will cause xTCPTimerCheck()
- to be called just before the IP-task blocks. */
- xProcessedTCPMessage++;
- }
- break;
+ /* Setting this variable will cause xTCPTimerCheck()
+ to be called just before the IP-task blocks. */
+ xProcessedTCPMessage++;
+ }
+ break;
#endif
- default :
- /* Not a supported frame type. */
- break;
+ default :
+ /* Not a supported frame type. */
+ break;
+ }
+ }
}
}
@@ -1703,12 +1882,12 @@ uint8_t ucProtocol;
/* Find the first byte of the data within the ICMP packet. */
pucByte = ( uint8_t * ) pxICMPPacket;
- pucByte += sizeof( ICMPPacket_t );
+ pucByte = &( pucByte[ sizeof( ICMPPacket_t ) ] );
/* Check each byte. */
for( usCount = 0; usCount < usDataLength; usCount++ )
{
- if( *pucByte != ipECHO_DATA_FILL_BYTE )
+ if( *pucByte != ( uint8_t ) ipECHO_DATA_FILL_BYTE )
{
eStatus = eInvalidData;
break;
@@ -1754,17 +1933,13 @@ uint8_t ucProtocol;
usRequest = ( uint16_t ) ( ( uint16_t )ipICMP_ECHO_REQUEST << 8 );
- if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFu - usRequest ) )
+ if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFU - usRequest ) )
{
- pxICMPHeader->usChecksum = ( uint16_t )
- ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
- FreeRTOS_htons( usRequest + 1UL ) );
+ pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest + 1U );
}
else
{
- pxICMPHeader->usChecksum = ( uint16_t )
- ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
- FreeRTOS_htons( usRequest ) );
+ pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest );
}
return eReturnEthernetFrame;
}
@@ -1798,6 +1973,7 @@ uint8_t ucProtocol;
break;
default :
+ /* Only ICMP echo packets are handled. */
break;
}
@@ -1807,6 +1983,126 @@ uint8_t ucProtocol;
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
/*-----------------------------------------------------------*/
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
+ /* Although the driver will take care of checksum calculations,
+ the IP-task will still check if the length fields are OK. */
+ static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength )
+ {
+ size_t uxLength;
+ const IPPacket_t * pxIPPacket;
+ UBaseType_t uxIPHeaderLength;
+ ProtocolPacket_t *pxProtPack;
+ uint8_t ucProtocol;
+ uint16_t usLength;
+ uint16_t ucVersionHeaderLength;
+ BaseType_t xLocation = 0;
+ size_t uxMinimumLength;
+ BaseType_t xResult = pdFAIL;
+
+ do
+ {
+ /* Check for minimum packet size: Ethernet header and an IP-header, 34 bytes */
+ if( uxBufferLength < sizeof( IPPacket_t ) )
+ {
+ xLocation = 1;
+ break;
+ }
+
+ /* Map the buffer onto a IP-Packet struct to easily access the
+ * fields of the IP packet. */
+ pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
+
+ ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
+ /* Test if the length of the IP-header is between 20 and 60 bytes,
+ and if the IP-version is 4. */
+ if( ( ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
+ ( ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
+ {
+ xLocation = 2;
+ break;
+ }
+ ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
+ uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
+
+ /* Check if the complete IP-header is transferred. */
+ if( uxBufferLength < ( ipSIZE_OF_ETH_HEADER + uxIPHeaderLength ) )
+ {
+ xLocation = 3;
+ break;
+ }
+ /* Check if the complete IP-header plus protocol data have been transferred: */
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
+ {
+ xLocation = 4;
+ break;
+ }
+
+ /* Identify the next protocol. */
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+
+ /* If this IP packet header includes Options, then the following
+ assignment results in a pointer into the protocol packet with the Ethernet
+ and IP headers incorrectly aligned. However, either way, the "third"
+ protocol (Layer 3 or 4) header will be aligned, which is the convenience
+ of this calculation. */
+ /* Map the Buffer onto the Protocol Packet struct for easy access to the
+ * struct fields. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+
+ /* Switch on the Layer 3/4 protocol. */
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
+ {
+ /* Expect at least a complete UDP header. */
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER;
+ }
+ else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
+ {
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER;
+ }
+ else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
+ ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
+ {
+ uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER;
+ }
+ else
+ {
+ /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
+ xLocation = 5;
+ break;
+ }
+ if( uxBufferLength < uxMinimumLength )
+ {
+ xLocation = 6;
+ break;
+ }
+
+ uxLength = ( size_t ) usLength;
+ uxLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally, minus 20. */
+
+ if( ( uxLength < ( ( size_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
+ ( uxLength > ( ( size_t ) ipconfigNETWORK_MTU - ( size_t ) uxIPHeaderLength ) ) )
+ {
+ /* For incoming packets, the length is out of bound: either
+ too short or too long. For outgoing packets, there is a
+ serious problem with the format/length. */
+ xLocation = 7;
+ break;
+ }
+ xResult = pdPASS;
+ } while( ipFALSE_BOOL );
+
+ if( xResult != pdPASS )
+ {
+ FreeRTOS_printf( ( "xCheckSizeFields: location %ld\n", xLocation ) );
+ }
+
+ return xResult;
+ }
+#endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
+/*-----------------------------------------------------------*/
+
uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength, BaseType_t xOutgoingPacket )
{
uint32_t ulLength;
@@ -1818,193 +2114,263 @@ uint8_t ucProtocol;
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
const char *pcType;
#endif
+uint16_t usLength;
+uint16_t ucVersionHeaderLength;
- /* Check for minimum packet size. */
- if( uxBufferLength < sizeof( IPPacket_t ) )
- {
- return ipINVALID_LENGTH;
- }
-
- /* Parse the packet length. */
- pxIPPacket = ( const IPPacket_t * ) pucEthernetBuffer;
- /* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
- Length field contains the length of the internet header in 32-bit words. */
- uxIPHeaderLength = ( UBaseType_t ) ( sizeof( uint32_t ) * ( pxIPPacket->xIPHeader.ucVersionHeaderLength & 0x0Fu ) );
+BaseType_t location = 0;
- /* Check for minimum packet size. */
- if( uxBufferLength < sizeof( IPPacket_t ) + uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER )
+ /* Introduce a do-while loop to allow use of break statements.
+ * Note: MISRA prohibits use of 'goto', thus replaced with breaks. */
+ do
{
- return ipINVALID_LENGTH;
- }
- if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) ) )
- {
- return ipINVALID_LENGTH;
- }
+ /* Check for minimum packet size. */
+ if( uxBufferLength < sizeof( IPPacket_t ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 1;
+ break;
+ }
- /* Identify the next protocol. */
- ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+ /* Parse the packet length. */
+ pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
- /* N.B., if this IP packet header includes Options, then the following
- assignment results in a pointer into the protocol packet with the Ethernet
- and IP headers incorrectly aligned. However, either way, the "third"
- protocol (Layer 3 or 4) header will be aligned, which is the convenience
- of this calculation. */
- pxProtPack = ( ProtocolPacket_t * ) ( pucEthernetBuffer + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) );
+ /* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
+ Length field contains the length of the internet header in 32-bit words. */
+ ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
+ ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
+ uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
- /* Switch on the Layer 3/4 protocol. */
- if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
+ /* Check for minimum packet size. */
+ if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
- return ipINVALID_LENGTH;
+ usChecksum = ipINVALID_LENGTH;
+ location = 2;
+ break;
}
-
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
- pcType = "UDP";
+ usChecksum = ipINVALID_LENGTH;
+ location = 3;
+ break;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
+
+ /* Identify the next protocol. */
+ ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
+
+ /* N.B., if this IP packet header includes Options, then the following
+ assignment results in a pointer into the protocol packet with the Ethernet
+ and IP headers incorrectly aligned. However, either way, the "third"
+ protocol (Layer 3 or 4) header will be aligned, which is the convenience
+ of this calculation. */
+ pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
+
+ /* Switch on the Layer 3/4 protocol. */
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
{
- return ipINVALID_LENGTH;
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 4;
+ break;
+ }
+
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ pcType = "UDP";
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
+ else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
+ {
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 5;
+ break;
+ }
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ pcType = "TCP";
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ }
+ else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
+ ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
{
- pcType = "TCP";
+ if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
+ {
+ usChecksum = ipINVALID_LENGTH;
+ location = 6;
+ break;
+ }
+
+ pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+ {
+ pcType = "ICMP";
+ }
+ else
+ {
+ pcType = "IGMP";
+ }
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
- ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
- {
- if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
+ else
{
- return ipINVALID_LENGTH;
+ /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
+ usChecksum = ipUNHANDLED_PROTOCOL;
+ location = 7;
+ break;
}
- pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ /* The protocol and checksum field have been identified. Check the direction
+ of the packet. */
+ if( xOutgoingPacket != pdFALSE )
+ {
+ /* This is an outgoing packet. Before calculating the checksum, set it
+ to zero. */
+ *( pusChecksum ) = 0U;
+ }
+ else if( ( *pusChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
- if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+ #if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
- pcType = "ICMP";
+ /* Sender hasn't set the checksum, drop the packet because
+ ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is not set. */
+ usChecksum = ipWRONG_CRC;
+ #if( ipconfigHAS_PRINTF != 0 )
+ {
+ static BaseType_t xCount = 0;
+
+ if( xCount < 5 )
+ {
+ FreeRTOS_printf( ( "usGenerateProtocolChecksum: UDP packet from %xip without CRC dropped\n",
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
+ xCount++;
+ }
+ }
+ #endif /* ( ipconfigHAS_PRINTF != 0 ) */
}
- else
+ #else
{
- pcType = "IGMP";
+ /* Sender hasn't set the checksum, no use to calculate it. */
+ usChecksum = ipCORRECT_CRC;
}
+ #endif
+ location = 8;
+ break;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- }
- else
- {
- /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
- return ipUNHANDLED_PROTOCOL;
- }
-
- /* The protocol and checksum field have been identified. Check the direction
- of the packet. */
- if( xOutgoingPacket != pdFALSE )
- {
- /* This is an outgoing packet. Before calculating the checksum, set it
- to zero. */
- *( pusChecksum ) = 0u;
- }
- else if( ( *pusChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
- {
- /* Sender hasn't set the checksum, no use to calculate it. */
- return ipCORRECT_CRC;
- }
-
- ulLength = ( uint32_t )
- ( FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) - ( ( uint16_t ) uxIPHeaderLength ) ); /* normally minus 20 */
-
- if( ( ulLength < sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ||
- ( ulLength > ( uint32_t )( ipconfigNETWORK_MTU - uxIPHeaderLength ) ) )
- {
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ else
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
+ /* Other incoming packet than UDP. */
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- /* Again, in a 16-bit return value there is no space to indicate an
- error. For incoming packets, 0x1234 will cause dropping of the packet.
- For outgoing packets, there is a serious problem with the
- format/length */
- return ipINVALID_LENGTH;
- }
- if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
- {
- /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
- usChecksum = ( uint16_t )
- ( ~usGenerateChecksum( 0UL,
- ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
- }
- else
- {
- /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
- fields */
- usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
+ usLength = pxIPPacket->xIPHeader.usLength;
+ usLength = FreeRTOS_ntohs( usLength );
+ ulLength = ( uint32_t ) usLength;
+ ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
- /* And then continue at the IPv4 source and destination addresses. */
- usChecksum = ( uint16_t )
- ( ~usGenerateChecksum( ( uint32_t ) usChecksum, ( uint8_t * )&( pxIPPacket->xIPHeader.ulSourceIPAddress ),
- ( 2u * sizeof( pxIPPacket->xIPHeader.ulSourceIPAddress ) + ulLength ) ) );
+ if( ( ulLength < ( ( uint32_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
+ ( ulLength > ( ( uint32_t ) ipconfigNETWORK_MTU - ( uint32_t ) uxIPHeaderLength ) ) )
+ {
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
- /* Sum TCP header and data. */
- }
+ /* Again, in a 16-bit return value there is no space to indicate an
+ error. For incoming packets, 0x1234 will cause dropping of the packet.
+ For outgoing packets, there is a serious problem with the
+ format/length */
+ usChecksum = ipINVALID_LENGTH;
+ location = 9;
+ break;
+ }
+ if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
+ {
+ /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
+ usChecksum = ( uint16_t )
+ ( ~usGenerateChecksum( 0U,
+ ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
+ }
+ else
+ {
+ /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
+ fields */
+ usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
+
+ /* And then continue at the IPv4 source and destination addresses. */
+ usChecksum = ( uint16_t )
+ ( ~usGenerateChecksum( usChecksum,
+ ipPOINTER_CAST( const uint8_t *, &( pxIPPacket->xIPHeader.ulSourceIPAddress ) ),
+ ( size_t )( ( 2U * ipSIZE_OF_IPv4_ADDRESS ) + ulLength ) ) );
+ /* Sum TCP header and data. */
+ }
- if( xOutgoingPacket == pdFALSE )
- {
- /* This is in incoming packet. If the CRC is correct, it should be zero. */
- if( usChecksum == 0u )
+ if( xOutgoingPacket == pdFALSE )
{
- usChecksum = ( uint16_t )ipCORRECT_CRC;
+ /* This is in incoming packet. If the CRC is correct, it should be zero. */
+ if( usChecksum == 0U )
+ {
+ usChecksum = ( uint16_t )ipCORRECT_CRC;
+ }
}
- }
- else
- {
- if( ( usChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
+ else
{
- /* In case of UDP, a calculated checksum of 0x0000 is transmitted
- as 0xffff. A value of zero would mean that the checksum is not used. */
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
- if( xOutgoingPacket != pdFALSE )
+ /* In case of UDP, a calculated checksum of 0x0000 is transmitted
+ as 0xffff. A value of zero would mean that the checksum is not used. */
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
+ if( xOutgoingPacket != pdFALSE )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
+ }
}
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+
+ usChecksum = ( uint16_t )0xffffu;
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ }
+ usChecksum = FreeRTOS_htons( usChecksum );
- usChecksum = ( uint16_t )0xffffu;
+ if( xOutgoingPacket != pdFALSE )
+ {
+ *( pusChecksum ) = usChecksum;
}
- }
- usChecksum = FreeRTOS_htons( usChecksum );
+ #if( ipconfigHAS_DEBUG_PRINTF != 0 )
+ else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
+ {
+ FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
+ pcType,
+ FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
+ FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
+ FreeRTOS_ntohs( *pusChecksum ) ) );
+ }
+ else
+ {
+ /* Nothing. */
+ }
+ #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
+ } while( ipFALSE_BOOL );
- if( xOutgoingPacket != pdFALSE )
- {
- *( pusChecksum ) = usChecksum;
- }
- #if( ipconfigHAS_DEBUG_PRINTF != 0 )
- else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
+ if( ( usChecksum == ipUNHANDLED_PROTOCOL ) ||
+ ( usChecksum == ipINVALID_LENGTH ) )
{
- FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
- pcType,
- FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
- FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
- FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
- FreeRTOS_ntohs( *pusChecksum ) ) );
+ FreeRTOS_printf( ( "CRC error: %04x location %ld\n", usChecksum, location ) );
}
- #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
return usChecksum;
}
@@ -2043,44 +2409,51 @@ uint8_t ucProtocol;
* uxDataLengthBytes: This argument contains the number of bytes that this method
* should process.
*/
-uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes )
+uint16_t usGenerateChecksum( uint16_t usSum, const uint8_t * pucNextData, size_t uxByteCount )
{
+/* MISRA/PC-lint doesn't like the use of unions. Here, they are a great
+aid though to optimise the calculations. */
xUnion32 xSum2, xSum, xTerm;
-xUnionPtr xSource; /* Points to first byte */
-xUnionPtr xLastSource; /* Points to last byte plus one */
-uint32_t ulAlignBits, ulCarry = 0ul;
+xUnionPtr xSource;
+xUnionPtr xLastSource;
+uint32_t ulAlignBits, ulCarry = 0UL;
+uint16_t usTemp;
+size_t uxDataLengthBytes = uxByteCount;
/* Small MCUs often spend up to 30% of the time doing checksum calculations
This function is optimised for 32-bit CPUs; Each time it will try to fetch
32-bits, sums it with an accumulator and counts the number of carries. */
/* Swap the input (little endian platform only). */
- xSum.u32 = FreeRTOS_ntohs( ulSum );
- xTerm.u32 = 0ul;
+ usTemp = FreeRTOS_ntohs( usSum );
+ xSum.u32 = ( uint32_t ) usTemp;
+ xTerm.u32 = 0UL;
- xSource.u8ptr = ( uint8_t * ) pucNextData;
- ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03u ); /* gives 0, 1, 2, or 3 */
+ xSource.u8ptr = ipPOINTER_CAST( uint8_t *, pucNextData );
+ /* coverity[misra_c_2012_rule_11_4_violation] */
+ /* The object pointer expression "pucNextData" of type "uint8_t const *" is cast to an integer type "unsigned int". */
+ ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03U ); /*lint !e9078 !e923*/ /* gives 0, 1, 2, or 3 */
/* If byte (8-bit) aligned... */
- if( ( ( ulAlignBits & 1ul ) != 0ul ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )
+ if( ( ( ulAlignBits & 1UL ) != 0UL ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )
{
xTerm.u8[ 1 ] = *( xSource.u8ptr );
- ( xSource.u8ptr )++;
+ xSource.u8ptr++;
uxDataLengthBytes--;
/* Now xSource is word (16-bit) aligned. */
}
/* If half-word (16-bit) aligned... */
- if( ( ( ulAlignBits == 1u ) || ( ulAlignBits == 2u ) ) && ( uxDataLengthBytes >= 2u ) )
+ if( ( ( ulAlignBits == 1U ) || ( ulAlignBits == 2U ) ) && ( uxDataLengthBytes >= 2U ) )
{
xSum.u32 += *(xSource.u16ptr);
- ( xSource.u16ptr )++;
- uxDataLengthBytes -= 2u;
+ xSource.u16ptr++;
+ uxDataLengthBytes -= 2U;
/* Now xSource is word (32-bit) aligned. */
}
/* Word (32-bit) aligned, do the most part. */
- xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4u ) ) - 3u;
+ xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4U ) ) - 3U;
/* In this loop, four 32-bit additions will be done, in total 16 bytes.
Indexing with constants (0,1,2,3) gives faster code than using
@@ -2118,16 +2491,19 @@ uint32_t ulAlignBits, ulCarry = 0ul;
}
/* And finally advance the pointer 4 * 4 = 16 bytes. */
- xSource.u32ptr += 4;
+ xSource.u32ptr = &( xSource.u32ptr[ 4 ] );
}
/* Now add all carries. */
xSum.u32 = ( uint32_t )xSum.u16[ 0 ] + xSum.u16[ 1 ] + ulCarry;
- uxDataLengthBytes %= 16u;
+ uxDataLengthBytes %= 16U;
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
/* Half-word aligned. */
+ /* Coverity does not like Unions. Warning issued here: "The operator "<"
+ * is being applied to the pointers "xSource.u16ptr" and "xLastSource.u16ptr",
+ * which do not point into the same object." */
while( xSource.u16ptr < xLastSource.u16ptr )
{
/* At least one more short. */
@@ -2135,23 +2511,25 @@ uint32_t ulAlignBits, ulCarry = 0ul;
xSource.u16ptr++;
}
- if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0u ) /* Maybe one more ? */
+ if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0U ) /* Maybe one more ? */
{
xTerm.u8[ 0 ] = xSource.u8ptr[ 0 ];
}
xSum.u32 += xTerm.u32;
/* Now add all carries again. */
+ /* Assigning value from "xTerm.u32" to "xSum.u32" here, but that stored value is overwritten before it can be used.
+ Coverity doesn't understand about union variables. */
xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
- /* The previous summation might have given a 16-bit carry. */
+ /* coverity[value_overwrite] */
xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
- if( ( ulAlignBits & 1u ) != 0u )
+ if( ( ulAlignBits & 1U ) != 0U )
{
/* Quite unlikely, but pucNextData might be non-aligned, which would
mean that a checksum is calculated starting at an odd position. */
- xSum.u32 = ( ( xSum.u32 & 0xffu ) << 8 ) | ( ( xSum.u32 & 0xff00u ) >> 8 );
+ xSum.u32 = ( ( xSum.u32 & 0xffU ) << 8 ) | ( ( xSum.u32 & 0xff00U ) >> 8 );
}
/* swap the output (little endian platform only). */
@@ -2159,6 +2537,8 @@ uint32_t ulAlignBits, ulCarry = 0ul;
}
/*-----------------------------------------------------------*/
+/* This function is used in other files, has external linkage e.g. in
+ * FreeRTOS_DNS.c. Not to be made static. */
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
EthernetHeader_t *pxEthernetHeader;
@@ -2173,10 +2553,10 @@ EthernetHeader_t *pxEthernetHeader;
{
BaseType_t xIndex;
- FreeRTOS_printf( ( "vReturnEthernetFrame: length %lu\n", ( uint32_t )pxNetworkBuffer->xDataLength ) );
+ FreeRTOS_printf( ( "vReturnEthernetFrame: length %u\n", ( unsigned ) pxNetworkBuffer->xDataLength ) );
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{
- pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
+ pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
}
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
}
@@ -2187,26 +2567,110 @@ EthernetHeader_t *pxEthernetHeader;
if( xReleaseAfterSend == pdFALSE )
{
- pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );
+ pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength );
xReleaseAfterSend = pdTRUE;
+ /* Want no rounding up. */
+ pxNewBuffer->xDataLength = pxNetworkBuffer->xDataLength;
pxNetworkBuffer = pxNewBuffer;
}
if( pxNetworkBuffer != NULL )
#endif
{
- pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
+ /* Map the Buffer to Ethernet Header struct for easy access to fields. */
+ pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
/* Swap source and destination MAC addresses. */
- memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );
- memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ), &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );
+ ( void ) memcpy( &( pxEthernetHeader->xSourceAddress) , ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
/* Send! */
- xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
+ ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
}
}
/*-----------------------------------------------------------*/
+
+#if ( ipconfigHAS_PRINTF != 0 )
+
+ #ifndef ipMONITOR_MAX_HEAP
+ /* As long as the heap has more space than e.g. 1 MB, there
+ will be no messages. */
+ #define ipMONITOR_MAX_HEAP ( 1024U * 1024U )
+ #endif /* ipMONITOR_MAX_HEAP */
+
+ #ifndef ipMONITOR_PERCENTAGE_90
+ /* Make this number lower to get less logging messages. */
+ #define ipMONITOR_PERCENTAGE_90 ( 90U )
+ #endif
+
+ #define ipMONITOR_PERCENTAGE_100 ( 100U )
+
+ void vPrintResourceStats( void )
+ {
+ static UBaseType_t uxLastMinBufferCount = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
+ static size_t uxMinLastSize = 0u;
+ UBaseType_t uxCurrentBufferCount;
+ size_t uxMinSize;
+
+ /* When setting up and testing a project with FreeRTOS+TCP, it is
+ can be helpful to monitor a few resources: the number of network
+ buffers and the amount of available heap.
+ This function will issue some logging when a minimum value has
+ changed. */
+ uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
+
+ if( uxLastMinBufferCount > uxCurrentBufferCount )
+ {
+ /* The logging produced below may be helpful
+ * while tuning +TCP: see how many buffers are in use. */
+ uxLastMinBufferCount = uxCurrentBufferCount;
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
+ uxGetNumberOfFreeNetworkBuffers(),
+ uxCurrentBufferCount ) );
+ }
+
+ uxMinSize = xPortGetMinimumEverFreeHeapSize();
+ if( uxMinLastSize == 0U )
+ {
+ /* Probably the first time this function is called. */
+ uxMinLastSize = uxMinSize;
+ }
+ else if( uxMinSize >= ipMONITOR_MAX_HEAP )
+ {
+ /* There is more than enough heap space. No need for logging. */
+ }
+ /* Write logging if there is a 10% decrease since the last time logging was written. */
+ else if( ( uxMinLastSize * ipMONITOR_PERCENTAGE_90 ) > ( uxMinSize * ipMONITOR_PERCENTAGE_100 ) )
+ {
+ uxMinLastSize = uxMinSize;
+ FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );
+ }
+ else
+ {
+ /* Nothing to log. */
+ }
+
+ #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
+ {
+ static UBaseType_t uxLastMinQueueSpace = 0;
+ UBaseType_t uxCurrentCount = 0u;
+
+ uxCurrentCount = uxGetMinimumIPQueueSpace();
+
+ if( uxLastMinQueueSpace != uxCurrentCount )
+ {
+ /* The logging produced below may be helpful
+ * while tuning +TCP: see how many buffers are in use. */
+ uxLastMinQueueSpace = uxCurrentCount;
+ FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
+ }
+ }
+ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
+ }
+#endif /* ( ipconfigHAS_PRINTF != 0 ) */
+/*-----------------------------------------------------------*/
+
uint32_t FreeRTOS_GetIPAddress( void )
{
/* Returns the IP address of the NIC. */
@@ -2242,7 +2706,7 @@ uint32_t FreeRTOS_GetNetmask( void )
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] )
{
/* Copy the MAC address at the start of the default packet header fragment. */
- memcpy( ( void * )ipLOCAL_MAC_ADDRESS, ( void * )ucMACAddress, ( size_t )ipMAC_ADDRESS_LENGTH_BYTES );
+ ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
}
/*-----------------------------------------------------------*/
@@ -2329,6 +2793,48 @@ BaseType_t FreeRTOS_IsNetworkUp( void )
}
#endif
/*-----------------------------------------------------------*/
+/* Utility function: Convert error number to a human readable
+ * string. Decalartion in FreeRTOS_errno_TCP.h. */
+const char *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength )
+{
+const char *pcName;
+
+ switch( xErrnum )
+ {
+ case pdFREERTOS_ERRNO_EADDRINUSE: pcName = "EADDRINUSE"; break;
+ case pdFREERTOS_ERRNO_ENOMEM: pcName = "ENOMEM"; break;
+ case pdFREERTOS_ERRNO_EADDRNOTAVAIL: pcName = "EADDRNOTAVAIL"; break;
+ case pdFREERTOS_ERRNO_ENOPROTOOPT: pcName = "ENOPROTOOPT"; break;
+ case pdFREERTOS_ERRNO_EBADF: pcName = "EBADF"; break;
+ case pdFREERTOS_ERRNO_ENOSPC: pcName = "ENOSPC"; break;
+ case pdFREERTOS_ERRNO_ECANCELED: pcName = "ECANCELED"; break;
+ case pdFREERTOS_ERRNO_ENOTCONN: pcName = "ENOTCONN"; break;
+ case pdFREERTOS_ERRNO_EINPROGRESS: pcName = "EINPROGRESS"; break;
+ case pdFREERTOS_ERRNO_EOPNOTSUPP: pcName = "EOPNOTSUPP"; break;
+ case pdFREERTOS_ERRNO_EINTR: pcName = "EINTR"; break;
+ case pdFREERTOS_ERRNO_ETIMEDOUT: pcName = "ETIMEDOUT"; break;
+ case pdFREERTOS_ERRNO_EINVAL: pcName = "EINVAL"; break;
+ case pdFREERTOS_ERRNO_EWOULDBLOCK: pcName = "EWOULDBLOCK"; break; /* same as EAGAIN */
+ case pdFREERTOS_ERRNO_EISCONN: pcName = "EISCONN"; break;
+ default:
+ /* Using function "snprintf". */
+ ( void ) snprintf( pcBuffer, uxLength, "Errno %d", ( int32_t ) xErrnum );
+ pcName = NULL;
+ break;
+ }
+ if( pcName != NULL )
+ {
+ /* Using function "snprintf". */
+ ( void ) snprintf( pcBuffer, uxLength, "%s", pcName );
+ }
+ if( uxLength > 0U )
+ {
+ pcBuffer[ uxLength - 1U ] = '\0';
+ }
+
+ return pcBuffer;
+}
+/*-----------------------------------------------------------*/
/* Provide access to private members for verification. */
#ifdef FREERTOS_TCP_ENABLE_VERIFICATION