mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-17 10:17:45 -04:00
Sync with +TCP amazon-FreeRTOS (#158)
* DNS.c commit * IP.c commit * Add various source & header files
This commit is contained in:
parent
8e36bee30e
commit
e0d62163b0
8 changed files with 826 additions and 687 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue