mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-22 00:50:34 +08:00
Sync with +TCP amazon-FreeRTOS (#158)
* DNS.c commit * IP.c commit * Add various source & header files
This commit is contained in:

committed by
GitHub

parent
8e36bee30e
commit
e0d62163b0
@ -112,6 +112,9 @@ type. */
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Define the ASCII value of '.' (Period/Full-stop). */
|
||||||
|
#define ASCII_BASELINE_DOT 46U
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a socket and bind it to the standard DNS port number. Return the
|
* Create a socket and bind it to the standard DNS port number. Return the
|
||||||
* the created socket - or NULL if the socket could not be created or bound.
|
* the created socket - or NULL if the socket could not be created or bound.
|
||||||
@ -217,8 +220,7 @@ static uint32_t prvGetHostByName( const char *pcHostName,
|
|||||||
|
|
||||||
static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ];
|
static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ];
|
||||||
|
|
||||||
/* MISRA c 2012 rule 8.7: Below function may be used by
|
/* Utility function: Clear DNS cache by calling this function. */
|
||||||
external callees as well */
|
|
||||||
void FreeRTOS_dnsclear( void )
|
void FreeRTOS_dnsclear( void )
|
||||||
{
|
{
|
||||||
( void ) memset( xDNSCache, 0x0, sizeof( xDNSCache ) );
|
( void ) memset( xDNSCache, 0x0, sizeof( xDNSCache ) );
|
||||||
@ -327,9 +329,6 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
|
|||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( ipconfigUSE_DNS_CACHE == 1 )
|
#if( ipconfigUSE_DNS_CACHE == 1 )
|
||||||
|
|
||||||
/* MISRA c 2012 rule 8.7: Below function may be used by
|
|
||||||
external callees as well */
|
|
||||||
uint32_t FreeRTOS_dnslookup( const char *pcHostName )
|
uint32_t FreeRTOS_dnslookup( const char *pcHostName )
|
||||||
{
|
{
|
||||||
uint32_t ulIPAddress = 0UL;
|
uint32_t ulIPAddress = 0UL;
|
||||||
@ -501,8 +500,6 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
|
|||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( ipconfigDNS_USE_CALLBACKS == 0 )
|
#if( ipconfigDNS_USE_CALLBACKS == 0 )
|
||||||
/* MISRA c 2012 rule 8.7 ralxed since this function can
|
|
||||||
be called from external sources as well */
|
|
||||||
uint32_t FreeRTOS_gethostbyname( const char *pcHostName )
|
uint32_t FreeRTOS_gethostbyname( const char *pcHostName )
|
||||||
{
|
{
|
||||||
return prvPrepareLookup( pcHostName );
|
return prvPrepareLookup( pcHostName );
|
||||||
@ -532,8 +529,33 @@ TickType_t uxReadTimeOut_ticks = ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS;
|
|||||||
as gethostbyname() may be called from different threads */
|
as gethostbyname() may be called from different threads */
|
||||||
BaseType_t xHasRandom = pdFALSE;
|
BaseType_t xHasRandom = pdFALSE;
|
||||||
TickType_t uxIdentifier = 0U;
|
TickType_t uxIdentifier = 0U;
|
||||||
|
#if( ipconfigUSE_DNS_CACHE != 0 )
|
||||||
|
BaseType_t xLengthOk = pdFALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( ipconfigUSE_DNS_CACHE != 0 )
|
||||||
|
{
|
||||||
|
if( pcHostName != NULL )
|
||||||
|
{
|
||||||
|
size_t xLength = strlen( pcHostName ) + 1;
|
||||||
|
|
||||||
|
if( xLength <= ipconfigDNS_CACHE_NAME_LENGTH )
|
||||||
|
{
|
||||||
|
/* The name is not too long. */
|
||||||
|
xLengthOk = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FreeRTOS_printf( ( "prvPrepareLookup: name is too long ( %lu > %lu )\n",
|
||||||
|
( unsigned long ) xLength,
|
||||||
|
( unsigned long ) ipconfigDNS_CACHE_NAME_LENGTH ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( ( pcHostName != NULL ) && ( xLengthOk != pdFALSE ) )
|
||||||
|
#else
|
||||||
if( pcHostName != NULL )
|
if( pcHostName != NULL )
|
||||||
|
#endif /* ( ipconfigUSE_DNS_CACHE != 0 ) */
|
||||||
{
|
{
|
||||||
/* If the supplied hostname is IP address, convert it to uint32_t
|
/* If the supplied hostname is IP address, convert it to uint32_t
|
||||||
and return. */
|
and return. */
|
||||||
@ -647,7 +669,7 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
|
|||||||
if( xDNSSocket != NULL )
|
if( xDNSSocket != NULL )
|
||||||
{
|
{
|
||||||
/* Ideally we should check for the return value. But since we are passing
|
/* Ideally we should check for the return value. But since we are passing
|
||||||
correect parameters, and xDNSSocket is != NULL, the return value is
|
correct parameters, and xDNSSocket is != NULL, the return value is
|
||||||
going to be '0' i.e. success. Thus, return value is discarded */
|
going to be '0' i.e. success. Thus, return value is discarded */
|
||||||
( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, &( uxWriteTimeOut_ticks ), sizeof( TickType_t ) );
|
( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, &( uxWriteTimeOut_ticks ), sizeof( TickType_t ) );
|
||||||
( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, &( uxReadTimeOut_ticks ), sizeof( TickType_t ) );
|
( void ) FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, &( uxReadTimeOut_ticks ), sizeof( TickType_t ) );
|
||||||
@ -785,10 +807,12 @@ static const DNSMessage_t xDefaultPartDNSHeader =
|
|||||||
0 /* No additional authorities. */
|
0 /* No additional authorities. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Copy in the const part of the header. */
|
/* Copy in the const part of the header. Intentionally using different
|
||||||
|
* pointers with memcpy() to put the information in to correct place. */
|
||||||
( void ) memcpy( pucUDPPayloadBuffer, &( xDefaultPartDNSHeader ), sizeof( xDefaultPartDNSHeader ) );
|
( void ) memcpy( pucUDPPayloadBuffer, &( xDefaultPartDNSHeader ), sizeof( xDefaultPartDNSHeader ) );
|
||||||
|
|
||||||
/* Write in a unique identifier. */
|
/* Write in a unique identifier. Cast the Payload Buffer to DNSMessage_t
|
||||||
|
* to easily access fields of the DNS Message. */
|
||||||
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
|
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
|
||||||
pxDNSMessageHeader->usIdentifier = ( uint16_t ) uxIdentifier;
|
pxDNSMessageHeader->usIdentifier = ( uint16_t ) uxIdentifier;
|
||||||
|
|
||||||
@ -815,9 +839,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
|
|||||||
{
|
{
|
||||||
pucByte++;
|
pucByte++;
|
||||||
|
|
||||||
/* MISRA c 2012 rule 10.4 relaxed for increased readability.
|
while( ( *pucByte != ( uint8_t ) 0U ) && ( *pucByte != ( uint8_t ) ASCII_BASELINE_DOT ) )
|
||||||
Not writing 46U instead of '.' */
|
|
||||||
while( ( *pucByte != ( uint8_t ) 0U ) && ( *pucByte != ( uint8_t ) '.' ) )
|
|
||||||
{
|
{
|
||||||
pucByte++;
|
pucByte++;
|
||||||
}
|
}
|
||||||
@ -830,7 +852,8 @@ static const DNSMessage_t xDefaultPartDNSHeader =
|
|||||||
pucStart = pucByte;
|
pucStart = pucByte;
|
||||||
} while( *pucByte != ( uint8_t ) 0U );
|
} while( *pucByte != ( uint8_t ) 0U );
|
||||||
|
|
||||||
/* Finish off the record. */
|
/* Finish off the record. Cast the record onto DNSTail_t stucture to easily
|
||||||
|
* access the fields of the DNS Message. */
|
||||||
pxTail = ipPOINTER_CAST(DNSTail_t *, &( pucByte[ 1 ] ) );
|
pxTail = ipPOINTER_CAST(DNSTail_t *, &( pucByte[ 1 ] ) );
|
||||||
|
|
||||||
#if defined( _lint ) || defined( __COVERITY__ )
|
#if defined( _lint ) || defined( __COVERITY__ )
|
||||||
@ -1012,9 +1035,6 @@ when ipconfigDNS_USE_CALLBACKS == 1
|
|||||||
when ipconfigUSE_LLMNR == 1
|
when ipconfigUSE_LLMNR == 1
|
||||||
for testing purposes, by the module iot_test_freertos_tcp.c
|
for testing purposes, by the module iot_test_freertos_tcp.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* MISRA c 2012 rule 8.7: Function below may be used by external
|
|
||||||
callees as well. */
|
|
||||||
uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t *pxNetworkBuffer )
|
uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t *pxNetworkBuffer )
|
||||||
{
|
{
|
||||||
DNSMessage_t *pxDNSMessageHeader;
|
DNSMessage_t *pxDNSMessageHeader;
|
||||||
@ -1076,6 +1096,8 @@ uint8_t *pucByte;
|
|||||||
size_t uxSourceBytesRemaining;
|
size_t uxSourceBytesRemaining;
|
||||||
uint16_t x, usDataLength, usQuestions;
|
uint16_t x, usDataLength, usQuestions;
|
||||||
uint16_t usType = 0U;
|
uint16_t usType = 0U;
|
||||||
|
BaseType_t xReturn = pdTRUE;
|
||||||
|
|
||||||
#if( ipconfigUSE_LLMNR == 1 )
|
#if( ipconfigUSE_LLMNR == 1 )
|
||||||
uint16_t usClass = 0U;
|
uint16_t usClass = 0U;
|
||||||
#endif
|
#endif
|
||||||
@ -1087,316 +1109,342 @@ uint16_t usType = 0U;
|
|||||||
/* Ensure that the buffer is of at least minimal DNS message length. */
|
/* Ensure that the buffer is of at least minimal DNS message length. */
|
||||||
if( uxBufferLength < sizeof( DNSMessage_t ) )
|
if( uxBufferLength < sizeof( DNSMessage_t ) )
|
||||||
{
|
{
|
||||||
return dnsPARSE_ERROR;
|
xReturn = pdFALSE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
uxSourceBytesRemaining = uxBufferLength;
|
|
||||||
|
|
||||||
/* Parse the DNS message header.
|
|
||||||
MISRA c 2012 rule 11.3 relaxed to make byte by byte traversal easier */
|
|
||||||
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
|
|
||||||
|
|
||||||
/* Introduce a do {} while (0) to allow the use of breaks. */
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
size_t uxBytesRead = 0U;
|
uxSourceBytesRemaining = uxBufferLength;
|
||||||
size_t uxResult;
|
|
||||||
|
|
||||||
/* Start at the first byte after the header. */
|
/* Parse the DNS message header. Map the byte stream onto a structure
|
||||||
pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] );
|
* for easier access. */
|
||||||
uxSourceBytesRemaining -= sizeof( DNSMessage_t );
|
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
|
||||||
|
|
||||||
/* Skip any question records. */
|
/* Introduce a do {} while (0) to allow the use of breaks. */
|
||||||
usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
|
do
|
||||||
|
|
||||||
for( x = 0U; x < usQuestions; x++ )
|
|
||||||
{
|
{
|
||||||
#if( ipconfigUSE_LLMNR == 1 )
|
size_t uxBytesRead = 0U;
|
||||||
{
|
size_t uxResult;
|
||||||
if( x == 0U )
|
|
||||||
{
|
|
||||||
pcRequestedName = ( char * ) pucByte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
|
/* Start at the first byte after the header. */
|
||||||
if( x == 0U )
|
pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] );
|
||||||
{
|
uxSourceBytesRemaining -= sizeof( DNSMessage_t );
|
||||||
uxResult = prvReadNameField( pucByte,
|
|
||||||
uxSourceBytesRemaining,
|
|
||||||
pcName,
|
|
||||||
sizeof( pcName ) );
|
|
||||||
|
|
||||||
/* Check for a malformed response. */
|
/* Skip any question records. */
|
||||||
if( uxResult == 0U )
|
usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
|
||||||
{
|
|
||||||
return dnsPARSE_ERROR;
|
|
||||||
}
|
|
||||||
uxBytesRead += uxResult;
|
|
||||||
pucByte = &( pucByte[ uxResult ] );
|
|
||||||
uxSourceBytesRemaining -= uxResult;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
|
|
||||||
{
|
|
||||||
/* Skip the variable length pcName field. */
|
|
||||||
uxResult = prvSkipNameField( pucByte,
|
|
||||||
uxSourceBytesRemaining );
|
|
||||||
|
|
||||||
/* Check for a malformed response. */
|
for( x = 0U; x < usQuestions; x++ )
|
||||||
if( uxResult == 0U )
|
|
||||||
{
|
|
||||||
return dnsPARSE_ERROR;
|
|
||||||
}
|
|
||||||
uxBytesRead += uxResult;
|
|
||||||
pucByte = &( pucByte[ uxResult ] );
|
|
||||||
uxSourceBytesRemaining -= uxResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the remaining buffer size. */
|
|
||||||
if( uxSourceBytesRemaining >= sizeof( uint32_t ) )
|
|
||||||
{
|
{
|
||||||
#if( ipconfigUSE_LLMNR == 1 )
|
#if( ipconfigUSE_LLMNR == 1 )
|
||||||
{
|
{
|
||||||
/* usChar2u16 returns value in host endianness. */
|
if( x == 0U )
|
||||||
usType = usChar2u16( pucByte );
|
{
|
||||||
usClass = usChar2u16( &( pucByte[ 2 ] ) );
|
pcRequestedName = ( char * ) pucByte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* ipconfigUSE_LLMNR */
|
#endif
|
||||||
|
|
||||||
/* Skip the type and class fields. */
|
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
|
||||||
pucByte = &( pucByte[ sizeof( uint32_t ) ] );
|
if( x == 0U )
|
||||||
uxSourceBytesRemaining -= sizeof( uint32_t );
|
{
|
||||||
|
uxResult = prvReadNameField( pucByte,
|
||||||
|
uxSourceBytesRemaining,
|
||||||
|
pcName,
|
||||||
|
sizeof( pcName ) );
|
||||||
|
|
||||||
|
/* Check for a malformed response. */
|
||||||
|
if( uxResult == 0U )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uxBytesRead += uxResult;
|
||||||
|
pucByte = &( pucByte[ uxResult ] );
|
||||||
|
uxSourceBytesRemaining -= uxResult;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
|
||||||
|
{
|
||||||
|
/* Skip the variable length pcName field. */
|
||||||
|
uxResult = prvSkipNameField( pucByte,
|
||||||
|
uxSourceBytesRemaining );
|
||||||
|
|
||||||
|
/* Check for a malformed response. */
|
||||||
|
if( uxResult == 0U )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uxBytesRead += uxResult;
|
||||||
|
pucByte = &( pucByte[ uxResult ] );
|
||||||
|
uxSourceBytesRemaining -= uxResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the remaining buffer size. */
|
||||||
|
if( uxSourceBytesRemaining >= sizeof( uint32_t ) )
|
||||||
|
{
|
||||||
|
#if( ipconfigUSE_LLMNR == 1 )
|
||||||
|
{
|
||||||
|
/* usChar2u16 returns value in host endianness. */
|
||||||
|
usType = usChar2u16( pucByte );
|
||||||
|
usClass = usChar2u16( &( pucByte[ 2 ] ) );
|
||||||
|
}
|
||||||
|
#endif /* ipconfigUSE_LLMNR */
|
||||||
|
|
||||||
|
/* Skip the type and class fields. */
|
||||||
|
pucByte = &( pucByte[ sizeof( uint32_t ) ] );
|
||||||
|
uxSourceBytesRemaining -= sizeof( uint32_t );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xReturn == pdFALSE )
|
||||||
|
{
|
||||||
|
/* No need to proceed. Break out of the do-while loop. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search through the answer records. */
|
||||||
|
pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );
|
||||||
|
|
||||||
|
if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )
|
||||||
|
{
|
||||||
|
const uint16_t usCount = ( uint16_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY;
|
||||||
|
uint16_t usNumARecordsStored = 0;
|
||||||
|
|
||||||
|
for( x = 0U; ( x < pxDNSMessageHeader->usAnswers ) && ( usNumARecordsStored < usCount ); x++ )
|
||||||
|
{
|
||||||
|
BaseType_t xDoAccept;
|
||||||
|
|
||||||
|
uxResult = prvSkipNameField( pucByte,
|
||||||
|
uxSourceBytesRemaining );
|
||||||
|
|
||||||
|
/* Check for a malformed response. */
|
||||||
|
if( uxResult == 0U )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uxBytesRead += uxResult;
|
||||||
|
pucByte = &( pucByte[ uxResult ] );
|
||||||
|
uxSourceBytesRemaining -= uxResult;
|
||||||
|
|
||||||
|
/* Is there enough data for an IPv4 A record answer and, if so,
|
||||||
|
is this an A record? */
|
||||||
|
if( uxSourceBytesRemaining < sizeof( uint16_t ) )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usType = usChar2u16( pucByte );
|
||||||
|
|
||||||
|
if( usType == ( uint16_t ) dnsTYPE_A_HOST )
|
||||||
|
{
|
||||||
|
if( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + ipSIZE_OF_IPv4_ADDRESS ) )
|
||||||
|
{
|
||||||
|
xDoAccept = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xDoAccept = pdFALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Unknown host type. */
|
||||||
|
xDoAccept = pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xDoAccept != pdFALSE )
|
||||||
|
{
|
||||||
|
/* This is the required record type and is of sufficient size. */
|
||||||
|
/* Mapping pucByte to a DNSAnswerRecord allows easy access of the
|
||||||
|
* fields of the structure. */
|
||||||
|
pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
|
||||||
|
|
||||||
|
/* Sanity check the data length of an IPv4 answer. */
|
||||||
|
if( FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ) == ( uint16_t ) sizeof( uint32_t ) )
|
||||||
|
{
|
||||||
|
/* Copy the IP address out of the record. Using different pointers
|
||||||
|
* to copy only the portion we want is intentional here. */
|
||||||
|
( void ) memcpy( &( ulIPAddress ),
|
||||||
|
&( pucByte[ sizeof( DNSAnswerRecord_t ) ] ),
|
||||||
|
sizeof( uint32_t ) );
|
||||||
|
|
||||||
|
#if( ipconfigDNS_USE_CALLBACKS == 1 )
|
||||||
|
{
|
||||||
|
/* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */
|
||||||
|
if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE )
|
||||||
|
{
|
||||||
|
/* This device has requested this DNS look-up.
|
||||||
|
The result may be stored in the DNS cache. */
|
||||||
|
xDoStore = pdTRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ipconfigDNS_USE_CALLBACKS == 1 */
|
||||||
|
#if( ipconfigUSE_DNS_CACHE == 1 )
|
||||||
|
{
|
||||||
|
char cBuffer[ 16 ];
|
||||||
|
|
||||||
|
/* The reply will only be stored in the DNS cache when the
|
||||||
|
request was issued by this device. */
|
||||||
|
if( xDoStore != pdFALSE )
|
||||||
|
{
|
||||||
|
( void ) prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE );
|
||||||
|
usNumARecordsStored++; /* Track # of A records stored */
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeRTOS_inet_ntop( FREERTOS_AF_INET, ( const void * ) &( ulIPAddress ), cBuffer, sizeof( cBuffer ) );
|
||||||
|
/* Show what has happened. */
|
||||||
|
FreeRTOS_printf( ( "DNS[0x%04lX]: The answer to '%s' (%s) will%s be stored\n",
|
||||||
|
( UBaseType_t ) pxDNSMessageHeader->usIdentifier,
|
||||||
|
pcName,
|
||||||
|
cBuffer,
|
||||||
|
( xDoStore != 0 ) ? "" : " NOT" ) );
|
||||||
|
}
|
||||||
|
#endif /* ipconfigUSE_DNS_CACHE */
|
||||||
|
}
|
||||||
|
|
||||||
|
pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ] );
|
||||||
|
uxSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) );
|
||||||
|
}
|
||||||
|
else if( uxSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) )
|
||||||
|
{
|
||||||
|
/* It's not an A record, so skip it. Get the header location
|
||||||
|
and then jump over the header. */
|
||||||
|
/* Cast the response to DNSAnswerRecord for easy access to fields of the DNS response. */
|
||||||
|
pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
|
||||||
|
|
||||||
|
pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) ] );
|
||||||
|
uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t );
|
||||||
|
|
||||||
|
/* Determine the length of the answer data from the header. */
|
||||||
|
usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength );
|
||||||
|
|
||||||
|
/* Jump over the answer. */
|
||||||
|
if( uxSourceBytesRemaining >= usDataLength )
|
||||||
|
{
|
||||||
|
pucByte = &( pucByte[ usDataLength ] );
|
||||||
|
uxSourceBytesRemaining -= usDataLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Malformed response. */
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( ipconfigUSE_LLMNR == 1 )
|
||||||
|
else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) && ( pcRequestedName != NULL ) )
|
||||||
|
{
|
||||||
|
/* If this is not a reply to our DNS request, it might an LLMNR
|
||||||
|
request. */
|
||||||
|
if( xApplicationDNSQueryHook( &( pcRequestedName[ 1 ] ) ) != pdFALSE )
|
||||||
|
{
|
||||||
|
int16_t usLength;
|
||||||
|
NetworkBufferDescriptor_t *pxNewBuffer = NULL;
|
||||||
|
NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
|
||||||
|
LLMNRAnswer_t *pxAnswer;
|
||||||
|
uint8_t *pucNewBuffer = NULL;
|
||||||
|
|
||||||
|
if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )
|
||||||
|
{
|
||||||
|
size_t uxDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );
|
||||||
|
|
||||||
|
/* Set the size of the outgoing packet. */
|
||||||
|
pxNetworkBuffer->xDataLength = uxDataLength;
|
||||||
|
pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, uxDataLength + sizeof( LLMNRAnswer_t ) );
|
||||||
|
|
||||||
|
if( pxNewBuffer != NULL )
|
||||||
|
{
|
||||||
|
BaseType_t xOffset1, xOffset2;
|
||||||
|
|
||||||
|
xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer );
|
||||||
|
xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer );
|
||||||
|
|
||||||
|
pxNetworkBuffer = pxNewBuffer;
|
||||||
|
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
|
||||||
|
|
||||||
|
pucByte = &( pucNewBuffer[ xOffset1 ] );
|
||||||
|
pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] );
|
||||||
|
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucNewBuffer );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Just to indicate that the message may not be answered. */
|
||||||
|
pxNetworkBuffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The test on 'pucNewBuffer' is only to satisfy lint. */
|
||||||
|
if( ( pxNetworkBuffer != NULL ) && ( pucNewBuffer != NULL ) )
|
||||||
|
{
|
||||||
|
pxAnswer = ipPOINTER_CAST( LLMNRAnswer_t *, pucByte );
|
||||||
|
|
||||||
|
/* We leave 'usIdentifier' and 'usQuestions' untouched */
|
||||||
|
#ifndef _lint
|
||||||
|
vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */
|
||||||
|
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */
|
||||||
|
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */
|
||||||
|
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */
|
||||||
|
#endif /* lint */
|
||||||
|
|
||||||
|
pxAnswer->ucNameCode = dnsNAME_IS_OFFSET;
|
||||||
|
pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucNewBuffer );
|
||||||
|
|
||||||
|
#ifndef _lint
|
||||||
|
vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */
|
||||||
|
vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */
|
||||||
|
vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE );
|
||||||
|
vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 );
|
||||||
|
vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );
|
||||||
|
#endif /* lint */
|
||||||
|
usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucNewBuffer ) );
|
||||||
|
|
||||||
|
prvReplyDNSMessage( pxNetworkBuffer, usLength );
|
||||||
|
|
||||||
|
if( pxNewBuffer != NULL )
|
||||||
|
{
|
||||||
|
vReleaseNetworkBufferAndDescriptor( pxNewBuffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return dnsPARSE_ERROR;
|
/* Not an expected reply. */
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Search through the answer records. */
|
|
||||||
pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );
|
|
||||||
|
|
||||||
if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )
|
|
||||||
{
|
|
||||||
const uint16_t usCount = ( uint16_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY;
|
|
||||||
|
|
||||||
for( x = 0U; ( x < pxDNSMessageHeader->usAnswers ) && ( x < usCount ); x++ )
|
|
||||||
{
|
|
||||||
BaseType_t xDoAccept;
|
|
||||||
|
|
||||||
uxResult = prvSkipNameField( pucByte,
|
|
||||||
uxSourceBytesRemaining );
|
|
||||||
|
|
||||||
/* Check for a malformed response. */
|
|
||||||
if( uxResult == 0U )
|
|
||||||
{
|
|
||||||
return dnsPARSE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uxBytesRead += uxResult;
|
|
||||||
pucByte = &( pucByte[ uxResult ] );
|
|
||||||
uxSourceBytesRemaining -= uxResult;
|
|
||||||
|
|
||||||
/* Is there enough data for an IPv4 A record answer and, if so,
|
|
||||||
is this an A record? */
|
|
||||||
if( uxSourceBytesRemaining < sizeof( uint16_t ) )
|
|
||||||
{
|
|
||||||
return dnsPARSE_ERROR;
|
|
||||||
}
|
|
||||||
usType = usChar2u16( pucByte );
|
|
||||||
|
|
||||||
if( usType == ( uint16_t ) dnsTYPE_A_HOST )
|
|
||||||
{
|
|
||||||
if( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + ipSIZE_OF_IPv4_ADDRESS ) )
|
|
||||||
{
|
|
||||||
xDoAccept = pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xDoAccept = pdFALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Unknown host type. */
|
|
||||||
xDoAccept = pdFALSE;
|
|
||||||
}
|
|
||||||
if( xDoAccept != pdFALSE )
|
|
||||||
{
|
|
||||||
/* This is the required record type and is of sufficient size. */
|
|
||||||
/* MISRA c 2012 rule 11.3 relaxed. pucByte is used for byte-by-byte
|
|
||||||
traversal. */
|
|
||||||
pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
|
|
||||||
|
|
||||||
/* Sanity check the data length of an IPv4 answer. */
|
|
||||||
if( FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ) == ( uint16_t ) sizeof( uint32_t ) )
|
|
||||||
{
|
|
||||||
/* Copy the IP address out of the record. */
|
|
||||||
/* MISRA c 2012 rule 21.15 relaxed here since this seems
|
|
||||||
to be the least cumbersome way to get the IP address
|
|
||||||
from the record. */
|
|
||||||
( void ) memcpy( &( ulIPAddress ),
|
|
||||||
&( pucByte[ sizeof( DNSAnswerRecord_t ) ] ),
|
|
||||||
sizeof( uint32_t ) );
|
|
||||||
|
|
||||||
#if( ipconfigDNS_USE_CALLBACKS == 1 )
|
|
||||||
{
|
|
||||||
/* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */
|
|
||||||
if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE )
|
|
||||||
{
|
|
||||||
/* This device has requested this DNS look-up.
|
|
||||||
The result may be stored in the DNS cache. */
|
|
||||||
xDoStore = pdTRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* ipconfigDNS_USE_CALLBACKS == 1 */
|
|
||||||
#if( ipconfigUSE_DNS_CACHE == 1 )
|
|
||||||
{
|
|
||||||
/* The reply will only be stored in the DNS cache when the
|
|
||||||
request was issued by this device. */
|
|
||||||
if( xDoStore != pdFALSE )
|
|
||||||
{
|
|
||||||
( void ) prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Show what has happened. */
|
|
||||||
FreeRTOS_printf( ( "DNS[0x%04lX]: The answer to '%s' (%lxip) will%s be stored\n",
|
|
||||||
( UBaseType_t ) pxDNSMessageHeader->usIdentifier,
|
|
||||||
pcName,
|
|
||||||
( UBaseType_t ) FreeRTOS_ntohl( ulIPAddress ),
|
|
||||||
( xDoStore != 0 ) ? "" : " NOT" ) );
|
|
||||||
}
|
|
||||||
#endif /* ipconfigUSE_DNS_CACHE */
|
|
||||||
}
|
|
||||||
|
|
||||||
pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) ] );
|
|
||||||
uxSourceBytesRemaining -= ( sizeof( DNSAnswerRecord_t ) + sizeof( uint32_t ) );
|
|
||||||
}
|
|
||||||
else if( uxSourceBytesRemaining >= sizeof( DNSAnswerRecord_t ) )
|
|
||||||
{
|
|
||||||
/* It's not an A record, so skip it. Get the header location
|
|
||||||
and then jump over the header. */
|
|
||||||
|
|
||||||
/* MISRA c 2012 rule 11.3 relaxed as pucByte is being used in
|
|
||||||
various places to point to various parts of the DNS records */
|
|
||||||
pxDNSAnswerRecord = ipPOINTER_CAST( DNSAnswerRecord_t *, pucByte );
|
|
||||||
|
|
||||||
pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) ] );
|
|
||||||
uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t );
|
|
||||||
|
|
||||||
/* Determine the length of the answer data from the header. */
|
|
||||||
usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength );
|
|
||||||
|
|
||||||
/* Jump over the answer. */
|
|
||||||
if( uxSourceBytesRemaining >= usDataLength )
|
|
||||||
{
|
|
||||||
pucByte = &( pucByte[ usDataLength ] );
|
|
||||||
uxSourceBytesRemaining -= usDataLength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Malformed response. */
|
|
||||||
return dnsPARSE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Do nothing */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if( ipconfigUSE_LLMNR == 1 )
|
|
||||||
else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) && ( pcRequestedName != NULL ) )
|
|
||||||
{
|
|
||||||
/* If this is not a reply to our DNS request, it might an LLMNR
|
|
||||||
request. */
|
|
||||||
if( xApplicationDNSQueryHook( &( pcRequestedName[ 1 ] ) ) != pdFALSE )
|
|
||||||
{
|
|
||||||
int16_t usLength;
|
|
||||||
NetworkBufferDescriptor_t *pxNewBuffer = NULL;
|
|
||||||
NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );
|
|
||||||
LLMNRAnswer_t *pxAnswer;
|
|
||||||
uint8_t *pucNewBuffer = NULL;
|
|
||||||
|
|
||||||
if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )
|
|
||||||
{
|
|
||||||
size_t uxDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );
|
|
||||||
|
|
||||||
/* Set the size of the outgoing packet. */
|
|
||||||
pxNetworkBuffer->xDataLength = uxDataLength;
|
|
||||||
pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, uxDataLength + sizeof( LLMNRAnswer_t ) );
|
|
||||||
|
|
||||||
if( pxNewBuffer != NULL )
|
|
||||||
{
|
|
||||||
BaseType_t xOffset1, xOffset2;
|
|
||||||
|
|
||||||
xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer );
|
|
||||||
xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer );
|
|
||||||
|
|
||||||
pxNetworkBuffer = pxNewBuffer;
|
|
||||||
pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
|
|
||||||
|
|
||||||
pucByte = &( pucNewBuffer[ xOffset1 ] );
|
|
||||||
pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] );
|
|
||||||
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucNewBuffer );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Just to indicate that the message may not be answered. */
|
|
||||||
pxNetworkBuffer = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The test on 'pucNewBuffer' is only to satisfy lint. */
|
|
||||||
if( ( pxNetworkBuffer != NULL ) && ( pucNewBuffer != NULL ) )
|
|
||||||
{
|
|
||||||
pxAnswer = ipPOINTER_CAST( LLMNRAnswer_t *, pucByte );
|
|
||||||
|
|
||||||
/* We leave 'usIdentifier' and 'usQuestions' untouched */
|
|
||||||
#ifndef _lint
|
|
||||||
vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */
|
|
||||||
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */
|
|
||||||
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */
|
|
||||||
vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */
|
|
||||||
#endif /* lint */
|
|
||||||
|
|
||||||
pxAnswer->ucNameCode = dnsNAME_IS_OFFSET;
|
|
||||||
pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucNewBuffer );
|
|
||||||
|
|
||||||
#ifndef _lint
|
|
||||||
vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */
|
|
||||||
vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */
|
|
||||||
vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE );
|
|
||||||
vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 );
|
|
||||||
vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );
|
|
||||||
#endif /* lint */
|
|
||||||
usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucNewBuffer ) );
|
|
||||||
|
|
||||||
prvReplyDNSMessage( pxNetworkBuffer, usLength );
|
|
||||||
|
|
||||||
if( pxNewBuffer != NULL )
|
|
||||||
{
|
|
||||||
vReleaseNetworkBufferAndDescriptor( pxNewBuffer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not an expected reply. */
|
|
||||||
}
|
|
||||||
#endif /* ipconfigUSE_LLMNR == 1 */
|
#endif /* ipconfigUSE_LLMNR == 1 */
|
||||||
( void ) uxBytesRead;
|
( void ) uxBytesRead;
|
||||||
} while( ipFALSE_BOOL );
|
} while( ipFALSE_BOOL );
|
||||||
|
}
|
||||||
|
|
||||||
if( xExpected == pdFALSE )
|
if( xReturn == pdFALSE )
|
||||||
|
{
|
||||||
|
/* There was an error while parsing the DNS response. Return error code. */
|
||||||
|
ulIPAddress = dnsPARSE_ERROR;
|
||||||
|
}
|
||||||
|
else if( xExpected == pdFALSE )
|
||||||
{
|
{
|
||||||
/* Do not return a valid IP-address in case the reply was not expected. */
|
/* Do not return a valid IP-address in case the reply was not expected. */
|
||||||
ulIPAddress = 0UL;
|
ulIPAddress = 0UL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The IP-address found will be returned. */
|
||||||
|
}
|
||||||
|
|
||||||
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
|
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
|
||||||
( void ) xDoStore;
|
( void ) xDoStore;
|
||||||
#endif
|
#endif
|
||||||
@ -1567,22 +1615,25 @@ BaseType_t xReturn;
|
|||||||
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
|
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
|
||||||
if( ( xSocket == FREERTOS_INVALID_SOCKET ) || ( xSocket == NULL ) )
|
if( ( xSocket == FREERTOS_INVALID_SOCKET ) || ( xSocket == NULL ) )
|
||||||
{
|
{
|
||||||
return NULL;
|
/* There was an error, return NULL. */
|
||||||
}
|
|
||||||
|
|
||||||
/* Auto bind the port. */
|
|
||||||
xAddress.sin_port = 0U;
|
|
||||||
xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
|
|
||||||
|
|
||||||
/* Check the bind was successful, and clean up if not. */
|
|
||||||
if( xReturn != 0 )
|
|
||||||
{
|
|
||||||
( void ) FreeRTOS_closesocket( xSocket );
|
|
||||||
xSocket = NULL;
|
xSocket = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The send and receive timeouts will be set later on. */
|
/* Auto bind the port. */
|
||||||
|
xAddress.sin_port = 0U;
|
||||||
|
xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
|
||||||
|
|
||||||
|
/* Check the bind was successful, and clean up if not. */
|
||||||
|
if( xReturn != 0 )
|
||||||
|
{
|
||||||
|
( void ) FreeRTOS_closesocket( xSocket );
|
||||||
|
xSocket = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The send and receive timeouts will be set later on. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xSocket;
|
return xSocket;
|
||||||
@ -1651,9 +1702,6 @@ BaseType_t xReturn;
|
|||||||
uint32_t ulIPAddressIndex = 0;
|
uint32_t ulIPAddressIndex = 0;
|
||||||
static BaseType_t xFreeEntry = 0;
|
static BaseType_t xFreeEntry = 0;
|
||||||
|
|
||||||
/* MISRA advisory rule 1.2 Relaxed in case of
|
|
||||||
configASSERT as using __FUNCTION__ makes
|
|
||||||
debugging easier */
|
|
||||||
configASSERT( ( pcName != NULL ) );
|
configASSERT( ( pcName != NULL ) );
|
||||||
|
|
||||||
/* For each entry in the DNS cache table. */
|
/* For each entry in the DNS cache table. */
|
||||||
@ -1736,7 +1784,7 @@ BaseType_t xReturn;
|
|||||||
xDNSCache[ xFreeEntry ].ucCurrentIPAddress = 0;
|
xDNSCache[ xFreeEntry ].ucCurrentIPAddress = 0;
|
||||||
|
|
||||||
/* Initialize all remaining IP addresses in this entry to 0 */
|
/* Initialize all remaining IP addresses in this entry to 0 */
|
||||||
memset( &xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ],
|
( void ) memset( &xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ],
|
||||||
0,
|
0,
|
||||||
sizeof( xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ] ) *
|
sizeof( xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ] ) *
|
||||||
( ( uint32_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY - 1U ) );
|
( ( uint32_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY - 1U ) );
|
||||||
|
@ -798,7 +798,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
|
|||||||
iptraceNETWORK_DOWN();
|
iptraceNETWORK_DOWN();
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
/* Utility function. Process Network Down event from ISR. */
|
||||||
BaseType_t FreeRTOS_NetworkDownFromISR( void )
|
BaseType_t FreeRTOS_NetworkDownFromISR( void )
|
||||||
{
|
{
|
||||||
static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
|
static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
|
||||||
@ -1288,6 +1288,7 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
|
|||||||
eFrameProcessingResult_t eReturn;
|
eFrameProcessingResult_t eReturn;
|
||||||
const EthernetHeader_t *pxEthernetHeader;
|
const EthernetHeader_t *pxEthernetHeader;
|
||||||
|
|
||||||
|
/* Map the buffer onto Ethernet Header struct for easy access to fields. */
|
||||||
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
|
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
|
||||||
|
|
||||||
if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
|
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 ) )
|
if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
|
||||||
{
|
{
|
||||||
eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
|
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 );
|
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
|
||||||
|
|
||||||
/* The condition "eReturned == eProcessBuffer" must be true. */
|
/* The condition "eReturned == eProcessBuffer" must be true. */
|
||||||
@ -1688,156 +1691,166 @@ uint8_t ucProtocol;
|
|||||||
if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
|
if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
|
||||||
( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
|
( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
|
||||||
{
|
{
|
||||||
return eReleaseBuffer;
|
eReturn = eReleaseBuffer;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
/* Are there IP-options. */
|
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
|
||||||
if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
|
/* 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.
|
/* Are there IP-options. */
|
||||||
The extra space is used for IP-options. */
|
if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
|
||||||
#if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
|
|
||||||
{
|
{
|
||||||
/* All structs of headers expect a IP header size of 20 bytes
|
/* The size of the IP-header is larger than 20 bytes.
|
||||||
* IP header options were included, we'll ignore them and cut them out. */
|
The extra space is used for IP-options. */
|
||||||
const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
|
#if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
|
||||||
/* From: the previous start of UDP/ICMP/TCP data. */
|
{
|
||||||
const uint8_t *pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
|
/* All structs of headers expect a IP header size of 20 bytes
|
||||||
/* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
|
* IP header options were included, we'll ignore them and cut them out. */
|
||||||
uint8_t *pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
|
const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
|
||||||
/* How many: total length minus the options and the lower headers. */
|
/* From: the previous start of UDP/ICMP/TCP data. */
|
||||||
const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
|
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 );
|
( void ) memmove( pucTarget, pucSource, xMoveLen );
|
||||||
pxNetworkBuffer->xDataLength -= optlen;
|
pxNetworkBuffer->xDataLength -= optlen;
|
||||||
|
|
||||||
/* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
|
/* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
|
||||||
pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
|
pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
|
||||||
( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
|
( ( 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
|
/* Add the IP and MAC addresses to the ARP table if they are not
|
||||||
IP-options will be dropped. */
|
already there - otherwise refresh the age of the existing
|
||||||
return eReleaseBuffer;
|
entry. */
|
||||||
}
|
if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
|
||||||
#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 )
|
|
||||||
{
|
{
|
||||||
if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
|
/* Refresh the ARP cache with the IP/MAC-address of the received
|
||||||
{
|
packet. For UDP packets, this will be done later in
|
||||||
ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
|
xProcessReceivedUDPPacket(), as soon as it's know that the message
|
||||||
if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
|
will be handled. This will prevent the ARP cache getting
|
||||||
{
|
overwritten with the IP address of useless broadcast packets. */
|
||||||
eReturn = prvProcessICMPPacket( pxICMPPacket );
|
vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
eReturn = eReleaseBuffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
|
switch( ucProtocol )
|
||||||
break;
|
|
||||||
|
|
||||||
case ipPROTOCOL_UDP :
|
|
||||||
{
|
{
|
||||||
/* The IP packet contained a UDP frame. */
|
case ipPROTOCOL_ICMP :
|
||||||
const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
|
/* The IP packet contained an ICMP frame. Don't bother checking
|
||||||
uint16_t usLength;
|
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
|
||||||
/* Note the header values required prior to the checksum
|
went wrong because it will not be able to validate what it
|
||||||
generation as the checksum pseudo header may clobber some of
|
receives. */
|
||||||
these values. */
|
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
|
||||||
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 );
|
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. */
|
case ipPROTOCOL_UDP :
|
||||||
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;
|
/* 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
eReturn = eReleaseBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if ipconfigUSE_TCP == 1
|
#if ipconfigUSE_TCP == 1
|
||||||
case ipPROTOCOL_TCP :
|
case ipPROTOCOL_TCP :
|
||||||
{
|
{
|
||||||
|
|
||||||
if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
|
if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
|
||||||
{
|
{
|
||||||
eReturn = eFrameConsumed;
|
eReturn = eFrameConsumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setting this variable will cause xTCPTimerCheck()
|
/* Setting this variable will cause xTCPTimerCheck()
|
||||||
to be called just before the IP-task blocks. */
|
to be called just before the IP-task blocks. */
|
||||||
xProcessedTCPMessage++;
|
xProcessedTCPMessage++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default :
|
default :
|
||||||
/* Not a supported frame type. */
|
/* Not a supported frame type. */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1995,7 +2008,8 @@ uint8_t ucProtocol;
|
|||||||
break;
|
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 );
|
pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
|
||||||
|
|
||||||
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
|
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
|
||||||
@ -2028,11 +2042,13 @@ uint8_t ucProtocol;
|
|||||||
/* Identify the next protocol. */
|
/* Identify the next protocol. */
|
||||||
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
|
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
|
assignment results in a pointer into the protocol packet with the Ethernet
|
||||||
and IP headers incorrectly aligned. However, either way, the "third"
|
and IP headers incorrectly aligned. However, either way, the "third"
|
||||||
protocol (Layer 3 or 4) header will be aligned, which is the convenience
|
protocol (Layer 3 or 4) header will be aligned, which is the convenience
|
||||||
of this calculation. */
|
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 ] ) );
|
pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
|
||||||
|
|
||||||
/* Switch on the Layer 3/4 protocol. */
|
/* Switch on the Layer 3/4 protocol. */
|
||||||
@ -2104,248 +2120,251 @@ uint16_t ucVersionHeaderLength;
|
|||||||
|
|
||||||
BaseType_t location = 0;
|
BaseType_t location = 0;
|
||||||
|
|
||||||
/* Check for minimum packet size. */
|
/* Introduce a do-while loop to allow use of break statements.
|
||||||
if( uxBufferLength < sizeof( IPPacket_t ) )
|
* Note: MISRA prohibits use of 'goto', thus replaced with breaks. */
|
||||||
|
do
|
||||||
{
|
{
|
||||||
usChecksum = ipINVALID_LENGTH;
|
/* Check for minimum packet size. */
|
||||||
location = 1;
|
if( uxBufferLength < sizeof( IPPacket_t ) )
|
||||||
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 ) )
|
|
||||||
{
|
{
|
||||||
usChecksum = ipINVALID_LENGTH;
|
usChecksum = ipINVALID_LENGTH;
|
||||||
location = 4;
|
location = 1;
|
||||||
goto error_exit;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
|
/* Parse the packet length. */
|
||||||
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
|
pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
|
||||||
{
|
|
||||||
pcType = "UDP";
|
/* 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. */
|
||||||
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
|
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
|
||||||
}
|
ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
|
||||||
else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
|
uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
|
||||||
{
|
|
||||||
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
|
/* Check for minimum packet size. */
|
||||||
|
if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
|
||||||
{
|
{
|
||||||
usChecksum = ipINVALID_LENGTH;
|
usChecksum = ipINVALID_LENGTH;
|
||||||
location = 5;
|
location = 2;
|
||||||
goto error_exit;
|
break;
|
||||||
}
|
}
|
||||||
|
usLength = pxIPPacket->xIPHeader.usLength;
|
||||||
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
|
usLength = FreeRTOS_ntohs( usLength );
|
||||||
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
|
if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
|
||||||
{
|
|
||||||
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;
|
usChecksum = ipINVALID_LENGTH;
|
||||||
location = 6;
|
location = 3;
|
||||||
goto error_exit;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
|
/* Identify the next protocol. */
|
||||||
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
|
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
|
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
|
||||||
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. */
|
|
||||||
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
|
#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 */
|
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
|
||||||
|
|
||||||
usChecksum = ( uint16_t )0xffffu;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
usChecksum = FreeRTOS_htons( usChecksum );
|
{
|
||||||
|
/* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
|
||||||
|
usChecksum = ipUNHANDLED_PROTOCOL;
|
||||||
|
location = 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if( xOutgoingPacket != pdFALSE )
|
/* The protocol and checksum field have been identified. Check the direction
|
||||||
{
|
of the packet. */
|
||||||
*( pusChecksum ) = usChecksum;
|
if( xOutgoingPacket != pdFALSE )
|
||||||
}
|
{
|
||||||
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
|
/* This is an outgoing packet. Before calculating the checksum, set it
|
||||||
else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
|
to zero. */
|
||||||
{
|
*( pusChecksum ) = 0U;
|
||||||
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
|
}
|
||||||
pcType,
|
else if( ( *pusChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
|
||||||
FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
|
{
|
||||||
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
|
#if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
|
||||||
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
|
{
|
||||||
FreeRTOS_ntohs( *pusChecksum ) ) );
|
/* Sender hasn't set the checksum, drop the packet because
|
||||||
}
|
ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is not set. */
|
||||||
else
|
usChecksum = ipWRONG_CRC;
|
||||||
{
|
#if( ipconfigHAS_PRINTF != 0 )
|
||||||
/* Nothing. */
|
{
|
||||||
}
|
static BaseType_t xCount = 0;
|
||||||
#endif /* ipconfigHAS_DEBUG_PRINTF != 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 ) ||
|
if( ( usChecksum == ipUNHANDLED_PROTOCOL ) ||
|
||||||
( usChecksum == ipINVALID_LENGTH ) )
|
( usChecksum == ipINVALID_LENGTH ) )
|
||||||
@ -2482,7 +2501,9 @@ size_t uxDataLengthBytes = uxByteCount;
|
|||||||
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
|
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
|
||||||
|
|
||||||
/* Half-word aligned. */
|
/* 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 )
|
while( xSource.u16ptr < xLastSource.u16ptr )
|
||||||
{
|
{
|
||||||
/* At least one more short. */
|
/* 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 )
|
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )
|
||||||
{
|
{
|
||||||
EthernetHeader_t *pxEthernetHeader;
|
EthernetHeader_t *pxEthernetHeader;
|
||||||
@ -2554,6 +2577,7 @@ EthernetHeader_t *pxEthernetHeader;
|
|||||||
if( pxNetworkBuffer != NULL )
|
if( pxNetworkBuffer != NULL )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/* Map the Buffer to Ethernet Header struct for easy access to fields. */
|
||||||
pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
|
pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
|
||||||
|
|
||||||
/* Swap source and destination MAC addresses. */
|
/* Swap source and destination MAC addresses. */
|
||||||
@ -2769,7 +2793,8 @@ BaseType_t FreeRTOS_IsNetworkUp( void )
|
|||||||
}
|
}
|
||||||
#endif
|
#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 *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength )
|
||||||
{
|
{
|
||||||
const char *pcName;
|
const char *pcName;
|
||||||
|
@ -874,6 +874,9 @@ NetworkBufferDescriptor_t xTempBuffer;
|
|||||||
usPacketIdentifier++;
|
usPacketIdentifier++;
|
||||||
pxIPHeader->usFragmentOffset = 0U;
|
pxIPHeader->usFragmentOffset = 0U;
|
||||||
|
|
||||||
|
/* Important: tell NIC driver how many bytes must be sent. */
|
||||||
|
pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
|
||||||
|
|
||||||
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
|
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
|
||||||
{
|
{
|
||||||
/* calculate the IP header checksum, in case the driver won't do that. */
|
/* calculate the IP header checksum, in case the driver won't do that. */
|
||||||
@ -899,9 +902,6 @@ NetworkBufferDescriptor_t xTempBuffer;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Important: tell NIC driver how many bytes must be sent. */
|
|
||||||
pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
|
|
||||||
|
|
||||||
/* Fill in the destination MAC addresses. */
|
/* Fill in the destination MAC addresses. */
|
||||||
( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ),
|
( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ),
|
||||||
&( pxEthernetHeader->xSourceAddress ),
|
&( pxEthernetHeader->xSourceAddress ),
|
||||||
@ -2000,6 +2000,7 @@ int32_t lCount, lLength;
|
|||||||
|
|
||||||
/* A txStream has been created already, see if the socket has new data for
|
/* A txStream has been created already, see if the socket has new data for
|
||||||
the sliding window.
|
the sliding window.
|
||||||
|
|
||||||
uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It
|
uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It
|
||||||
contains new Tx data which has not been passed to the sliding window yet.
|
contains new Tx data which has not been passed to the sliding window yet.
|
||||||
The oldest data not-yet-confirmed can be found at rxTail. */
|
The oldest data not-yet-confirmed can be found at rxTail. */
|
||||||
@ -2009,6 +2010,7 @@ int32_t lCount, lLength;
|
|||||||
{
|
{
|
||||||
/* All data between txMid and rxHead will now be passed to the sliding
|
/* All data between txMid and rxHead will now be passed to the sliding
|
||||||
window manager, so it can start transmitting them.
|
window manager, so it can start transmitting them.
|
||||||
|
|
||||||
Hand over the new data to the sliding window handler. It will be
|
Hand over the new data to the sliding window handler. It will be
|
||||||
split-up in chunks of 1460 bytes each (or less, depending on
|
split-up in chunks of 1460 bytes each (or less, depending on
|
||||||
ipconfigTCP_MSS). */
|
ipconfigTCP_MSS). */
|
||||||
@ -2141,6 +2143,7 @@ uint16_t usLength;
|
|||||||
|
|
||||||
/* Determine the length and the offset of the user-data sent to this
|
/* Determine the length and the offset of the user-data sent to this
|
||||||
node.
|
node.
|
||||||
|
|
||||||
The size of the TCP header is given in a multiple of 4-byte words (single
|
The size of the TCP header is given in a multiple of 4-byte words (single
|
||||||
byte, needs no ntoh() translation). A shift-right 2: is the same as
|
byte, needs no ntoh() translation). A shift-right 2: is the same as
|
||||||
(offset >> 4) * 4. */
|
(offset >> 4) * 4. */
|
||||||
@ -2216,6 +2219,7 @@ BaseType_t xResult = 0;
|
|||||||
{
|
{
|
||||||
/* See if way may accept the data contents and forward it to the socket
|
/* See if way may accept the data contents and forward it to the socket
|
||||||
owner.
|
owner.
|
||||||
|
|
||||||
If it can't be "accept"ed it may have to be stored and send a selective
|
If it can't be "accept"ed it may have to be stored and send a selective
|
||||||
ack (SACK) option to confirm it. In that case, lTCPAddRxdata() will be
|
ack (SACK) option to confirm it. In that case, lTCPAddRxdata() will be
|
||||||
called later to store an out-of-order packet (in case lOffset is
|
called later to store an out-of-order packet (in case lOffset is
|
||||||
@ -3504,3 +3508,4 @@ const ListItem_t *pxEndTCP = ipPOINTER_CAST( const ListItem_t *, listGET_END_MAR
|
|||||||
#ifdef FREERTOS_TCP_ENABLE_VERIFICATION
|
#ifdef FREERTOS_TCP_ENABLE_VERIFICATION
|
||||||
#include "aws_freertos_tcp_verification_access_tcp_define.h"
|
#include "aws_freertos_tcp_verification_access_tcp_define.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1910,8 +1910,8 @@ const int32_t l500ms = 500;
|
|||||||
|
|
||||||
#if( ipconfigUSE_TCP_WIN == 0 )
|
#if( ipconfigUSE_TCP_WIN == 0 )
|
||||||
|
|
||||||
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize );
|
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize );
|
||||||
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize )
|
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize )
|
||||||
{
|
{
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
|
|
||||||
@ -1934,7 +1934,7 @@ const int32_t l500ms = 500;
|
|||||||
|
|
||||||
BaseType_t xTCPWindowTxHasData( TCPWindow_t const *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
|
BaseType_t xTCPWindowTxHasData( TCPWindow_t const *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
|
||||||
{
|
{
|
||||||
TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );
|
TCPSegment_t const *pxSegment = &( pxWindow->xTxSegment );
|
||||||
BaseType_t xReturn;
|
BaseType_t xReturn;
|
||||||
TickType_t ulAge, ulMaxAge;
|
TickType_t ulAge, ulMaxAge;
|
||||||
|
|
||||||
|
@ -317,20 +317,25 @@ from the FreeRTOSIPConfig.h configuration header file. */
|
|||||||
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
|
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Configuration to control whether packets with IP options,
|
||||||
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
|
* received over the network, should be passed up to the
|
||||||
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
|
* software stack OR should be dropped.
|
||||||
#endif
|
* If set to 1, the stack accepts IP packets that contain IP options, but does
|
||||||
|
* not process the options (IP options are not supported).
|
||||||
#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
|
* If set to 0, the stack will drop IP packets that contain IP options.
|
||||||
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
|
*/
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
|
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
|
||||||
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
|
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Configuration to control whether UDP packets with
|
||||||
|
* checksum value of zero should be passed up the software
|
||||||
|
* stack OR should be dropped.
|
||||||
|
* If set to 1, the stack will accept UDP packets that have their checksum
|
||||||
|
* value set to 0.
|
||||||
|
* If set to 0, the stack will drop UDP packets that have their checksum value
|
||||||
|
* set to 0.
|
||||||
|
*/
|
||||||
#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
|
#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
|
||||||
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
|
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -304,6 +304,12 @@ BaseType_t FreeRTOS_IsNetworkUp( void );
|
|||||||
UBaseType_t uxGetMinimumIPQueueSpace( void );
|
UBaseType_t uxGetMinimumIPQueueSpace( void );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ( ipconfigHAS_PRINTF != 0 )
|
||||||
|
extern void vPrintResourceStats( void );
|
||||||
|
#else
|
||||||
|
#define vPrintResourceStats() do {} while( ipFALSE_BOOL )
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defined in FreeRTOS_Sockets.c
|
* Defined in FreeRTOS_Sockets.c
|
||||||
* //_RB_ Don't think this comment is correct. If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.
|
* //_RB_ Don't think this comment is correct. If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS+TCP V2.2.1
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dump_packets.c
|
* dump_packets.c
|
||||||
* Used in the PC/Win project to dump Ethernet packets, along with some description.
|
* Used in the PC/Win project to dump Ethernet packets, along with some description.
|
||||||
|
@ -1,3 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* FreeRTOS+TCP V2.2.1
|
||||||
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tcp_mem_stats.h
|
* tcp_mem_stats.h
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user