Sync with +TCP amazon-FreeRTOS (#158)

* DNS.c commit

* IP.c commit

* Add various source & header files
This commit is contained in:
Aniruddha Kanhere 2020-07-22 18:06:23 -07:00 committed by GitHub
parent 8e36bee30e
commit e0d62163b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 826 additions and 687 deletions

View file

@ -798,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 };
@ -1288,6 +1288,7 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
eFrameProcessingResult_t eReturn;
const EthernetHeader_t *pxEthernetHeader;
/* Map the buffer onto Ethernet Header struct for easy access to fields. */
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
@ -1427,6 +1428,8 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
{
eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( 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. */
@ -1688,156 +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
{
/* Are there IP-options. */
if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
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 )
{
/* 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 )
/* Are there IP-options. */
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. */
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 );
/* 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 )
{
/* 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;
( 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 );
/* 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 );
}
#else
{
/* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
IP-options will be dropped. */
eReturn = eReleaseBuffer;
}
#endif
}
#else
if( eReturn != eReleaseBuffer )
{
/* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
IP-options will be dropped. */
return eReleaseBuffer;
}
#endif
}
/* 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 )
/* 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 )
{
if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
{
ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
eReturn = prvProcessICMPPacket( pxICMPPacket );
}
}
else
{
eReturn = eReleaseBuffer;
}
/* 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 );
}
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
break;
case ipPROTOCOL_UDP :
switch( ucProtocol )
{
/* The IP packet contained a UDP frame. */
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 )
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;
}
}
}
}
@ -1995,7 +2008,8 @@ uint8_t ucProtocol;
break;
}
/* Parse the packet length. */
/* 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;
@ -2028,11 +2042,13 @@ uint8_t ucProtocol;
/* Identify the next protocol. */
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* N.B., if this IP packet header includes Options, then the following
/* 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. */
@ -2104,248 +2120,251 @@ uint16_t ucVersionHeaderLength;
BaseType_t location = 0;
/* Check for minimum packet size. */
if( uxBufferLength < sizeof( IPPacket_t ) )
/* Introduce a do-while loop to allow use of break statements.
* Note: MISRA prohibits use of 'goto', thus replaced with breaks. */
do
{
usChecksum = ipINVALID_LENGTH;
location = 1;
goto error_exit;
}
/* Parse the packet length. */
pxIPPacket = ipPOINTER_CAST( 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. */
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
/* Check for minimum packet size. */
if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
usChecksum = ipINVALID_LENGTH;
location = 2;
goto error_exit;
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
usChecksum = ipINVALID_LENGTH;
location = 3;
goto error_exit;
}
/* 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 )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
/* Check for minimum packet size. */
if( uxBufferLength < sizeof( IPPacket_t ) )
{
usChecksum = ipINVALID_LENGTH;
location = 4;
goto error_exit;
location = 1;
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 ) )
/* Parse the packet length. */
pxIPPacket = ipPOINTER_CAST( 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. */
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
/* Check for minimum packet size. */
if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
usChecksum = ipINVALID_LENGTH;
location = 5;
goto error_exit;
location = 2;
break;
}
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 ) )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
usChecksum = ipINVALID_LENGTH;
location = 6;
goto error_exit;
location = 3;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
/* 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 )
{
if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
{
pcType = "ICMP";
usChecksum = ipINVALID_LENGTH;
location = 4;
break;
}
else
{
pcType = "IGMP";
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else
{
/* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
usChecksum = ipUNHANDLED_PROTOCOL;
location = 7;
goto error_exit;
}
/* 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( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
/* 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
{
/* Sender hasn't set the checksum, no use to calculate it. */
usChecksum = ipCORRECT_CRC;
}
#endif
location = 8;
goto error_exit;
}
else
{
/* Other incoming packet than UDP. */
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
ulLength = ( uint32_t ) usLength;
ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
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 */
/* 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;
goto error_exit;
}
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 )
{
usChecksum = ( uint16_t )ipCORRECT_CRC;
}
}
else
{
if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
/* 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. */
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
if( xOutgoingPacket != pdFALSE )
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 )
{
pcType = "TCP";
}
#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 ) )
{
usChecksum = ipINVALID_LENGTH;
location = 6;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
pcType = "ICMP";
}
else
{
pcType = "IGMP";
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
usChecksum = ( uint16_t )0xffffu;
}
}
usChecksum = FreeRTOS_htons( usChecksum );
else
{
/* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
usChecksum = ipUNHANDLED_PROTOCOL;
location = 7;
break;
}
if( xOutgoingPacket != pdFALSE )
{
*( pusChecksum ) = 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 */
/* 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( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
/* 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;
error_exit:
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
{
/* Sender hasn't set the checksum, no use to calculate it. */
usChecksum = ipCORRECT_CRC;
}
#endif
location = 8;
break;
}
else
{
/* Other incoming packet than UDP. */
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
ulLength = ( uint32_t ) usLength;
ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
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 */
/* 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 )
{
usChecksum = ( uint16_t )ipCORRECT_CRC;
}
}
else
{
if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
/* 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( xOutgoingPacket != pdFALSE )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
usChecksum = ( uint16_t )0xffffu;
}
}
usChecksum = FreeRTOS_htons( usChecksum );
if( xOutgoingPacket != pdFALSE )
{
*( pusChecksum ) = 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( ( usChecksum == ipUNHANDLED_PROTOCOL ) ||
( usChecksum == ipINVALID_LENGTH ) )
@ -2482,7 +2501,9 @@ size_t uxDataLengthBytes = uxByteCount;
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
/* Half-word aligned. */
/* The operator "<" is being applied to the pointers "xSource.u16ptr" and "xLastSource.u16ptr", which do not point into the same object. */
/* 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. */
@ -2516,6 +2537,8 @@ size_t uxDataLengthBytes = uxByteCount;
}
/*-----------------------------------------------------------*/
/* 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;
@ -2554,6 +2577,7 @@ EthernetHeader_t *pxEthernetHeader;
if( pxNetworkBuffer != NULL )
#endif
{
/* 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. */
@ -2769,7 +2793,8 @@ 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;