mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-19 22:57:57 +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
|
||||
|
||||
/* 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 ) );
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_.
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
*/
|
||||
|
Reference in New Issue
Block a user