Sync with +TCP amazon-FreeRTOS (#158)

* DNS.c commit

* IP.c commit

* Add various source & header files
This commit is contained in:
Aniruddha Kanhere
2020-07-22 18:06:23 -07:00
committed by GitHub
parent 8e36bee30e
commit e0d62163b0
8 changed files with 826 additions and 687 deletions

View File

@ -112,6 +112,9 @@ type. */
#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
* 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 ];
/* MISRA c 2012 rule 8.7: Below function may be used by
external callees as well */
/* Utility function: Clear DNS cache by calling this function. */
void FreeRTOS_dnsclear( void )
{
( void ) memset( xDNSCache, 0x0, sizeof( xDNSCache ) );
@ -327,9 +329,6 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
/*-----------------------------------------------------------*/
#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 ulIPAddress = 0UL;
@ -501,8 +500,6 @@ typedef struct xDNSAnswerRecord DNSAnswerRecord_t;
/*-----------------------------------------------------------*/
#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 )
{
return prvPrepareLookup( pcHostName );
@ -532,8 +529,33 @@ TickType_t uxReadTimeOut_ticks = ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS;
as gethostbyname() may be called from different threads */
BaseType_t xHasRandom = pdFALSE;
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 )
#endif /* ( ipconfigUSE_DNS_CACHE != 0 ) */
{
/* If the supplied hostname is IP address, convert it to uint32_t
and return. */
@ -647,7 +669,7 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
if( xDNSSocket != NULL )
{
/* 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 */
( 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 ) );
@ -785,10 +807,12 @@ static const DNSMessage_t xDefaultPartDNSHeader =
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 ) );
/* 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->usIdentifier = ( uint16_t ) uxIdentifier;
@ -815,9 +839,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
{
pucByte++;
/* MISRA c 2012 rule 10.4 relaxed for increased readability.
Not writing 46U instead of '.' */
while( ( *pucByte != ( uint8_t ) 0U ) && ( *pucByte != ( uint8_t ) '.' ) )
while( ( *pucByte != ( uint8_t ) 0U ) && ( *pucByte != ( uint8_t ) ASCII_BASELINE_DOT ) )
{
pucByte++;
}
@ -830,7 +852,8 @@ static const DNSMessage_t xDefaultPartDNSHeader =
pucStart = pucByte;
} 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 ] ) );
#if defined( _lint ) || defined( __COVERITY__ )
@ -1012,9 +1035,6 @@ when ipconfigDNS_USE_CALLBACKS == 1
when ipconfigUSE_LLMNR == 1
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 )
{
DNSMessage_t *pxDNSMessageHeader;
@ -1076,6 +1096,8 @@ uint8_t *pucByte;
size_t uxSourceBytesRemaining;
uint16_t x, usDataLength, usQuestions;
uint16_t usType = 0U;
BaseType_t xReturn = pdTRUE;
#if( ipconfigUSE_LLMNR == 1 )
uint16_t usClass = 0U;
#endif
@ -1087,316 +1109,342 @@ uint16_t usType = 0U;
/* Ensure that the buffer is of at least minimal DNS message length. */
if( uxBufferLength < sizeof( DNSMessage_t ) )
{
return dnsPARSE_ERROR;
xReturn = pdFALSE;
}
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
else
{
size_t uxBytesRead = 0U;
size_t uxResult;
uxSourceBytesRemaining = uxBufferLength;
/* Start at the first byte after the header. */
pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] );
uxSourceBytesRemaining -= sizeof( DNSMessage_t );
/* Parse the DNS message header. Map the byte stream onto a structure
* for easier access. */
pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer );
/* Skip any question records. */
usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
for( x = 0U; x < usQuestions; x++ )
/* Introduce a do {} while (0) to allow the use of breaks. */
do
{
#if( ipconfigUSE_LLMNR == 1 )
{
if( x == 0U )
{
pcRequestedName = ( char * ) pucByte;
}
}
#endif
size_t uxBytesRead = 0U;
size_t uxResult;
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
if( x == 0U )
{
uxResult = prvReadNameField( pucByte,
uxSourceBytesRemaining,
pcName,
sizeof( pcName ) );
/* Start at the first byte after the header. */
pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] );
uxSourceBytesRemaining -= sizeof( DNSMessage_t );
/* Check for a malformed response. */
if( uxResult == 0U )
{
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 );
/* Skip any question records. */
usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );
/* Check for a malformed response. */
if( uxResult == 0U )
{
return dnsPARSE_ERROR;
}
uxBytesRead += uxResult;
pucByte = &( pucByte[ uxResult ] );
uxSourceBytesRemaining -= uxResult;
}
/* Check the remaining buffer size. */
if( uxSourceBytesRemaining >= sizeof( uint32_t ) )
for( x = 0U; x < usQuestions; x++ )
{
#if( ipconfigUSE_LLMNR == 1 )
{
/* usChar2u16 returns value in host endianness. */
usType = usChar2u16( pucByte );
usClass = usChar2u16( &( pucByte[ 2 ] ) );
if( x == 0U )
{
pcRequestedName = ( char * ) pucByte;
}
}
#endif /* ipconfigUSE_LLMNR */
#endif
/* Skip the type and class fields. */
pucByte = &( pucByte[ sizeof( uint32_t ) ] );
uxSourceBytesRemaining -= sizeof( uint32_t );
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
if( x == 0U )
{
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
{
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 */
( void ) uxBytesRead;
} while( ipFALSE_BOOL );
( void ) uxBytesRead;
} 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. */
ulIPAddress = 0UL;
}
else
{
/* The IP-address found will be returned. */
}
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
( void ) xDoStore;
#endif
@ -1567,22 +1615,25 @@ BaseType_t xReturn;
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
if( ( xSocket == FREERTOS_INVALID_SOCKET ) || ( xSocket == NULL ) )
{
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 );
/* There was an error, return NULL. */
xSocket = NULL;
}
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;
@ -1651,9 +1702,6 @@ BaseType_t xReturn;
uint32_t ulIPAddressIndex = 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 ) );
/* For each entry in the DNS cache table. */
@ -1736,7 +1784,7 @@ BaseType_t xReturn;
xDNSCache[ xFreeEntry ].ucCurrentIPAddress = 0;
/* Initialize all remaining IP addresses in this entry to 0 */
memset( &xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ],
( void ) memset( &xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ],
0,
sizeof( xDNSCache[ xFreeEntry ].ulIPAddresses[ 1 ] ) *
( ( uint32_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY - 1U ) );

View File

@ -798,7 +798,7 @@ const TickType_t xDontBlock = ( TickType_t ) 0;
iptraceNETWORK_DOWN();
}
/*-----------------------------------------------------------*/
/* Utility function. Process Network Down event from ISR. */
BaseType_t FreeRTOS_NetworkDownFromISR( void )
{
static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
@ -1288,6 +1288,7 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
eFrameProcessingResult_t eReturn;
const EthernetHeader_t *pxEthernetHeader;
/* Map the buffer onto Ethernet Header struct for easy access to fields. */
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pucEthernetBuffer );
if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
@ -1427,6 +1428,8 @@ eFrameProcessingResult_t eReturned = eReleaseBuffer;
if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
{
eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
/* Map the buffer onto the Ethernet Header struct for easy access to the fields. */
pxEthernetHeader = ipPOINTER_CAST( const EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
/* The condition "eReturned == eProcessBuffer" must be true. */
@ -1688,156 +1691,166 @@ uint8_t ucProtocol;
if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
{
return eReleaseBuffer;
eReturn = eReleaseBuffer;
}
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* Check if the IP headers are acceptable and if it has our destination. */
eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
if( eReturn == eProcessBuffer )
else
{
/* Are there IP-options. */
if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* Check if the IP headers are acceptable and if it has our destination. */
eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
if( eReturn == eProcessBuffer )
{
/* The size of the IP-header is larger than 20 bytes.
The extra space is used for IP-options. */
#if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
/* Are there IP-options. */
if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
{
/* All structs of headers expect a IP header size of 20 bytes
* IP header options were included, we'll ignore them and cut them out. */
const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
/* From: the previous start of UDP/ICMP/TCP data. */
const uint8_t *pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
/* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
uint8_t *pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
/* How many: total length minus the options and the lower headers. */
const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
/* The size of the IP-header is larger than 20 bytes.
The extra space is used for IP-options. */
#if( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
{
/* All structs of headers expect a IP header size of 20 bytes
* IP header options were included, we'll ignore them and cut them out. */
const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
/* From: the previous start of UDP/ICMP/TCP data. */
const uint8_t *pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
/* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
uint8_t *pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
/* How many: total length minus the options and the lower headers. */
const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
( void ) memmove( pucTarget, pucSource, xMoveLen );
pxNetworkBuffer->xDataLength -= optlen;
( void ) memmove( pucTarget, pucSource, xMoveLen );
pxNetworkBuffer->xDataLength -= optlen;
/* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
/* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
}
#else
{
/* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
IP-options will be dropped. */
eReturn = eReleaseBuffer;
}
#endif
}
#else
if( eReturn != eReleaseBuffer )
{
/* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
IP-options will be dropped. */
return eReleaseBuffer;
}
#endif
}
/* Add the IP and MAC addresses to the ARP table if they are not
already there - otherwise refresh the age of the existing
entry. */
if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
{
/* Refresh the ARP cache with the IP/MAC-address of the received
packet. For UDP packets, this will be done later in
xProcessReceivedUDPPacket(), as soon as it's know that the message
will be handled. This will prevent the ARP cache getting
overwritten with the IP address of useless broadcast packets. */
vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
}
switch( ucProtocol )
{
case ipPROTOCOL_ICMP :
/* The IP packet contained an ICMP frame. Don't bother checking
the ICMP checksum, as if it is wrong then the wrong data will
also be returned, and the source of the ping will know something
went wrong because it will not be able to validate what it
receives. */
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/* Add the IP and MAC addresses to the ARP table if they are not
already there - otherwise refresh the age of the existing
entry. */
if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
{
if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
{
ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
eReturn = prvProcessICMPPacket( pxICMPPacket );
}
}
else
{
eReturn = eReleaseBuffer;
}
/* Refresh the ARP cache with the IP/MAC-address of the received
packet. For UDP packets, this will be done later in
xProcessReceivedUDPPacket(), as soon as it's know that the message
will be handled. This will prevent the ARP cache getting
overwritten with the IP address of useless broadcast packets. */
vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
}
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
break;
case ipPROTOCOL_UDP :
switch( ucProtocol )
{
/* The IP packet contained a UDP frame. */
const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
uint16_t usLength;
/* Note the header values required prior to the checksum
generation as the checksum pseudo header may clobber some of
these values. */
usLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength );
if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) &&
( ( ( size_t ) usLength ) >= sizeof( UDPHeader_t ) ) )
{
size_t uxPayloadSize_1, uxPayloadSize_2;
/* Ensure that downstream UDP packet handling has the lesser
of: the actual network buffer Ethernet frame length, or
the sender's UDP packet header payload length, minus the
size of the UDP header.
The size of the UDP packet structure in this implementation
includes the size of the Ethernet header, the size of
the IP header, and the size of the UDP header. */
uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
uxPayloadSize_2 = ( ( size_t ) usLength ) - sizeof( UDPHeader_t );
if( uxPayloadSize_1 > uxPayloadSize_2 )
case ipPROTOCOL_ICMP :
/* The IP packet contained an ICMP frame. Don't bother checking
the ICMP checksum, as if it is wrong then the wrong data will
also be returned, and the source of the ping will know something
went wrong because it will not be able to validate what it
receives. */
#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
{
pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
{
/* Map the buffer onto a ICMP-Packet struct to easily access the
* fields of ICMP packet. */
ICMPPacket_t *pxICMPPacket = ipPOINTER_CAST( ICMPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{
eReturn = prvProcessICMPPacket( pxICMPPacket );
}
}
else
{
eReturn = eReleaseBuffer;
}
}
#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
break;
/* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
/* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
In some cases, the upper-layer checksum has been calculated
by the NIC driver. */
/* Pass the packet payload to the UDP sockets
implementation. */
if( xProcessReceivedUDPPacket( pxNetworkBuffer,
pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
case ipPROTOCOL_UDP :
{
eReturn = eFrameConsumed;
/* The IP packet contained a UDP frame. */
/* Map the buffer onto a UDP-Packet struct to easily access the
* fields of UDP packet. */
const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
uint16_t usLength;
/* Note the header values required prior to the checksum
generation as the checksum pseudo header may clobber some of
these values. */
usLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength );
if ( ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) ) &&
( ( ( size_t ) usLength ) >= sizeof( UDPHeader_t ) ) )
{
size_t uxPayloadSize_1, uxPayloadSize_2;
/* Ensure that downstream UDP packet handling has the lesser
of: the actual network buffer Ethernet frame length, or
the sender's UDP packet header payload length, minus the
size of the UDP header.
The size of the UDP packet structure in this implementation
includes the size of the Ethernet header, the size of
the IP header, and the size of the UDP header. */
uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
uxPayloadSize_2 = ( ( size_t ) usLength ) - sizeof( UDPHeader_t );
if( uxPayloadSize_1 > uxPayloadSize_2 )
{
pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
}
/* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
/* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
In some cases, the upper-layer checksum has been calculated
by the NIC driver. */
/* Pass the packet payload to the UDP sockets
implementation. */
if( xProcessReceivedUDPPacket( pxNetworkBuffer,
pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
{
eReturn = eFrameConsumed;
}
}
else
{
eReturn = eReleaseBuffer;
}
}
}
else
{
eReturn = eReleaseBuffer;
}
}
break;
break;
#if ipconfigUSE_TCP == 1
case ipPROTOCOL_TCP :
{
case ipPROTOCOL_TCP :
{
if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
{
eReturn = eFrameConsumed;
}
if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
{
eReturn = eFrameConsumed;
}
/* Setting this variable will cause xTCPTimerCheck()
to be called just before the IP-task blocks. */
xProcessedTCPMessage++;
}
break;
/* Setting this variable will cause xTCPTimerCheck()
to be called just before the IP-task blocks. */
xProcessedTCPMessage++;
}
break;
#endif
default :
/* Not a supported frame type. */
break;
default :
/* Not a supported frame type. */
break;
}
}
}
}
@ -1995,7 +2008,8 @@ uint8_t ucProtocol;
break;
}
/* Parse the packet length. */
/* Map the buffer onto a IP-Packet struct to easily access the
* fields of the IP packet. */
pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
@ -2028,11 +2042,13 @@ uint8_t ucProtocol;
/* Identify the next protocol. */
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* N.B., if this IP packet header includes Options, then the following
/* If this IP packet header includes Options, then the following
assignment results in a pointer into the protocol packet with the Ethernet
and IP headers incorrectly aligned. However, either way, the "third"
protocol (Layer 3 or 4) header will be aligned, which is the convenience
of this calculation. */
/* Map the Buffer onto the Protocol Packet struct for easy access to the
* struct fields. */
pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
/* Switch on the Layer 3/4 protocol. */
@ -2104,248 +2120,251 @@ uint16_t ucVersionHeaderLength;
BaseType_t location = 0;
/* Check for minimum packet size. */
if( uxBufferLength < sizeof( IPPacket_t ) )
/* Introduce a do-while loop to allow use of break statements.
* Note: MISRA prohibits use of 'goto', thus replaced with breaks. */
do
{
usChecksum = ipINVALID_LENGTH;
location = 1;
goto error_exit;
}
/* Parse the packet length. */
pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
/* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
Length field contains the length of the internet header in 32-bit words. */
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
/* Check for minimum packet size. */
if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
usChecksum = ipINVALID_LENGTH;
location = 2;
goto error_exit;
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
usChecksum = ipINVALID_LENGTH;
location = 3;
goto error_exit;
}
/* Identify the next protocol. */
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* N.B., if this IP packet header includes Options, then the following
assignment results in a pointer into the protocol packet with the Ethernet
and IP headers incorrectly aligned. However, either way, the "third"
protocol (Layer 3 or 4) header will be aligned, which is the convenience
of this calculation. */
pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
/* Switch on the Layer 3/4 protocol. */
if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
/* Check for minimum packet size. */
if( uxBufferLength < sizeof( IPPacket_t ) )
{
usChecksum = ipINVALID_LENGTH;
location = 4;
goto error_exit;
location = 1;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
pcType = "UDP";
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
/* Parse the packet length. */
pxIPPacket = ipPOINTER_CAST( const IPPacket_t *, pucEthernetBuffer );
/* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
Length field contains the length of the internet header in 32-bit words. */
ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
/* Check for minimum packet size. */
if( uxBufferLength < ( sizeof( IPPacket_t ) + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) ) )
{
usChecksum = ipINVALID_LENGTH;
location = 5;
goto error_exit;
location = 2;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
pcType = "TCP";
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
{
usChecksum = ipINVALID_LENGTH;
location = 6;
goto error_exit;
location = 3;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
/* Identify the next protocol. */
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
/* N.B., if this IP packet header includes Options, then the following
assignment results in a pointer into the protocol packet with the Ethernet
and IP headers incorrectly aligned. However, either way, the "third"
protocol (Layer 3 or 4) header will be aligned, which is the convenience
of this calculation. */
pxProtPack = ipPOINTER_CAST( ProtocolPacket_t *, &( pucEthernetBuffer[ uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
/* Switch on the Layer 3/4 protocol. */
if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
{
if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) )
{
pcType = "ICMP";
usChecksum = ipINVALID_LENGTH;
location = 4;
break;
}
else
{
pcType = "IGMP";
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else
{
/* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
usChecksum = ipUNHANDLED_PROTOCOL;
location = 7;
goto error_exit;
}
/* The protocol and checksum field have been identified. Check the direction
of the packet. */
if( xOutgoingPacket != pdFALSE )
{
/* This is an outgoing packet. Before calculating the checksum, set it
to zero. */
*( pusChecksum ) = 0U;
}
else if( ( *pusChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
#if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
/* Sender hasn't set the checksum, drop the packet because
ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is not set. */
usChecksum = ipWRONG_CRC;
#if( ipconfigHAS_PRINTF != 0 )
{
static BaseType_t xCount = 0;
if( xCount < 5 )
{
FreeRTOS_printf( ( "usGenerateProtocolChecksum: UDP packet from %xip without CRC dropped\n",
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
xCount++;
}
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
}
#else
{
/* Sender hasn't set the checksum, no use to calculate it. */
usChecksum = ipCORRECT_CRC;
}
#endif
location = 8;
goto error_exit;
}
else
{
/* Other incoming packet than UDP. */
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
ulLength = ( uint32_t ) usLength;
ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
if( ( ulLength < ( ( uint32_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
( ulLength > ( ( uint32_t ) ipconfigNETWORK_MTU - ( uint32_t ) uxIPHeaderLength ) ) )
{
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
/* Again, in a 16-bit return value there is no space to indicate an
error. For incoming packets, 0x1234 will cause dropping of the packet.
For outgoing packets, there is a serious problem with the
format/length */
usChecksum = ipINVALID_LENGTH;
location = 9;
goto error_exit;
}
if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
{
/* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
usChecksum = ( uint16_t )
( ~usGenerateChecksum( 0U,
( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
}
else
{
/* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
fields */
usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
/* And then continue at the IPv4 source and destination addresses. */
usChecksum = ( uint16_t )
( ~usGenerateChecksum( usChecksum,
ipPOINTER_CAST( const uint8_t *, &( pxIPPacket->xIPHeader.ulSourceIPAddress ) ),
( size_t )( ( 2U * ipSIZE_OF_IPv4_ADDRESS ) + ulLength ) ) );
/* Sum TCP header and data. */
}
if( xOutgoingPacket == pdFALSE )
{
/* This is in incoming packet. If the CRC is correct, it should be zero. */
if( usChecksum == 0U )
{
usChecksum = ( uint16_t )ipCORRECT_CRC;
}
}
else
{
if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
/* In case of UDP, a calculated checksum of 0x0000 is transmitted
as 0xffff. A value of zero would mean that the checksum is not used. */
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
if( xOutgoingPacket != pdFALSE )
pcType = "UDP";
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) )
{
usChecksum = ipINVALID_LENGTH;
location = 5;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
pcType = "TCP";
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
}
else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
{
if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) )
{
usChecksum = ipINVALID_LENGTH;
location = 6;
break;
}
pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
pcType = "ICMP";
}
else
{
pcType = "IGMP";
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
usChecksum = ( uint16_t )0xffffu;
}
}
usChecksum = FreeRTOS_htons( usChecksum );
else
{
/* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
usChecksum = ipUNHANDLED_PROTOCOL;
location = 7;
break;
}
if( xOutgoingPacket != pdFALSE )
{
*( pusChecksum ) = usChecksum;
}
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
pcType,
FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
FreeRTOS_ntohs( *pusChecksum ) ) );
}
else
{
/* Nothing. */
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
/* The protocol and checksum field have been identified. Check the direction
of the packet. */
if( xOutgoingPacket != pdFALSE )
{
/* This is an outgoing packet. Before calculating the checksum, set it
to zero. */
*( pusChecksum ) = 0U;
}
else if( ( *pusChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
#if( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
{
/* Sender hasn't set the checksum, drop the packet because
ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is not set. */
usChecksum = ipWRONG_CRC;
#if( ipconfigHAS_PRINTF != 0 )
{
static BaseType_t xCount = 0;
error_exit:
if( xCount < 5 )
{
FreeRTOS_printf( ( "usGenerateProtocolChecksum: UDP packet from %xip without CRC dropped\n",
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
xCount++;
}
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
}
#else
{
/* Sender hasn't set the checksum, no use to calculate it. */
usChecksum = ipCORRECT_CRC;
}
#endif
location = 8;
break;
}
else
{
/* Other incoming packet than UDP. */
}
usLength = pxIPPacket->xIPHeader.usLength;
usLength = FreeRTOS_ntohs( usLength );
ulLength = ( uint32_t ) usLength;
ulLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally minus 20 */
if( ( ulLength < ( ( uint32_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) ||
( ulLength > ( ( uint32_t ) ipconfigNETWORK_MTU - ( uint32_t ) uxIPHeaderLength ) ) )
{
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
/* Again, in a 16-bit return value there is no space to indicate an
error. For incoming packets, 0x1234 will cause dropping of the packet.
For outgoing packets, there is a serious problem with the
format/length */
usChecksum = ipINVALID_LENGTH;
location = 9;
break;
}
if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
{
/* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
usChecksum = ( uint16_t )
( ~usGenerateChecksum( 0U,
( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
}
else
{
/* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
fields */
usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
/* And then continue at the IPv4 source and destination addresses. */
usChecksum = ( uint16_t )
( ~usGenerateChecksum( usChecksum,
ipPOINTER_CAST( const uint8_t *, &( pxIPPacket->xIPHeader.ulSourceIPAddress ) ),
( size_t )( ( 2U * ipSIZE_OF_IPv4_ADDRESS ) + ulLength ) ) );
/* Sum TCP header and data. */
}
if( xOutgoingPacket == pdFALSE )
{
/* This is in incoming packet. If the CRC is correct, it should be zero. */
if( usChecksum == 0U )
{
usChecksum = ( uint16_t )ipCORRECT_CRC;
}
}
else
{
if( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
{
/* In case of UDP, a calculated checksum of 0x0000 is transmitted
as 0xffff. A value of zero would mean that the checksum is not used. */
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
{
if( xOutgoingPacket != pdFALSE )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
}
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
usChecksum = ( uint16_t )0xffffu;
}
}
usChecksum = FreeRTOS_htons( usChecksum );
if( xOutgoingPacket != pdFALSE )
{
*( pusChecksum ) = usChecksum;
}
#if( ipconfigHAS_DEBUG_PRINTF != 0 )
else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
{
FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
pcType,
FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
FreeRTOS_ntohs( *pusChecksum ) ) );
}
else
{
/* Nothing. */
}
#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
} while( ipFALSE_BOOL );
if( ( usChecksum == ipUNHANDLED_PROTOCOL ) ||
( usChecksum == ipINVALID_LENGTH ) )
@ -2482,7 +2501,9 @@ size_t uxDataLengthBytes = uxByteCount;
xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
/* Half-word aligned. */
/* The operator "<" is being applied to the pointers "xSource.u16ptr" and "xLastSource.u16ptr", which do not point into the same object. */
/* Coverity does not like Unions. Warning issued here: "The operator "<"
* is being applied to the pointers "xSource.u16ptr" and "xLastSource.u16ptr",
* which do not point into the same object." */
while( xSource.u16ptr < xLastSource.u16ptr )
{
/* At least one more short. */
@ -2516,6 +2537,8 @@ size_t uxDataLengthBytes = uxByteCount;
}
/*-----------------------------------------------------------*/
/* This function is used in other files, has external linkage e.g. in
* FreeRTOS_DNS.c. Not to be made static. */
void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
EthernetHeader_t *pxEthernetHeader;
@ -2554,6 +2577,7 @@ EthernetHeader_t *pxEthernetHeader;
if( pxNetworkBuffer != NULL )
#endif
{
/* Map the Buffer to Ethernet Header struct for easy access to fields. */
pxEthernetHeader = ipPOINTER_CAST( EthernetHeader_t *, pxNetworkBuffer->pucEthernetBuffer );
/* Swap source and destination MAC addresses. */
@ -2769,7 +2793,8 @@ BaseType_t FreeRTOS_IsNetworkUp( void )
}
#endif
/*-----------------------------------------------------------*/
/* Utility function: Convert error number to a human readable
* string. Decalartion in FreeRTOS_errno_TCP.h. */
const char *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength )
{
const char *pcName;

View File

@ -874,6 +874,9 @@ NetworkBufferDescriptor_t xTempBuffer;
usPacketIdentifier++;
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 )
{
/* calculate the IP header checksum, in case the driver won't do that. */
@ -899,9 +902,6 @@ NetworkBufferDescriptor_t xTempBuffer;
}
#endif
/* Important: tell NIC driver how many bytes must be sent. */
pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;
/* Fill in the destination MAC addresses. */
( void ) memcpy( &( pxEthernetHeader->xDestinationAddress ),
&( pxEthernetHeader->xSourceAddress ),
@ -2000,6 +2000,7 @@ int32_t lCount, lLength;
/* A txStream has been created already, see if the socket has new data for
the sliding window.
uxStreamBufferMidSpace() returns the distance between rxHead and rxMid. It
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. */
@ -2009,6 +2010,7 @@ int32_t lCount, lLength;
{
/* All data between txMid and rxHead will now be passed to the sliding
window manager, so it can start transmitting them.
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
ipconfigTCP_MSS). */
@ -2141,6 +2143,7 @@ uint16_t usLength;
/* Determine the length and the offset of the user-data sent to this
node.
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
(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
owner.
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
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
#include "aws_freertos_tcp_verification_access_tcp_define.h"
#endif

View File

@ -1910,8 +1910,8 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 )
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *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 );
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize )
{
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 )
{
TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );
TCPSegment_t const *pxSegment = &( pxWindow->xTxSegment );
BaseType_t xReturn;
TickType_t ulAge, ulMaxAge;

View File

@ -317,20 +317,25 @@ from the FreeRTOSIPConfig.h configuration header file. */
#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1
#endif
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
#endif
#ifndef ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
#endif
/* Configuration to control whether packets with IP options,
* received over the network, should be passed up to the
* software stack OR should be dropped.
* If set to 1, the stack accepts IP packets that contain IP options, but does
* not process the options (IP options are not supported).
* If set to 0, the stack will drop IP packets that contain IP options.
*/
#ifndef ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
#define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1
#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
#define ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS 0
#endif

View File

@ -304,6 +304,12 @@ BaseType_t FreeRTOS_IsNetworkUp( void );
UBaseType_t uxGetMinimumIPQueueSpace( void );
#endif
#if ( ipconfigHAS_PRINTF != 0 )
extern void vPrintResourceStats( void );
#else
#define vPrintResourceStats() do {} while( ipFALSE_BOOL )
#endif
/*
* 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_.

View File

@ -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
* Used in the PC/Win project to dump Ethernet packets, along with some description.

View File

@ -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
*/