diff options
author | Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> | 2020-07-22 18:06:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-22 18:06:23 -0700 |
commit | e0d62163b08769fd74f020709c398f994088ca96 (patch) | |
tree | a4530c1c98f5a8eaf56d0d969a33339eb0f4a1d3 /FreeRTOS-Plus | |
parent | 8e36bee30eef2107e128edb58e83ee46e8241a91 (diff) | |
download | freertos-git-e0d62163b08769fd74f020709c398f994088ca96.tar.gz |
Sync with +TCP amazon-FreeRTOS (#158)
* DNS.c commit
* IP.c commit
* Add various source & header files
Diffstat (limited to 'FreeRTOS-Plus')
8 files changed, 756 insertions, 617 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c index 18fe02932..fd2fe8507 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c @@ -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; } + else + { + uxSourceBytesRemaining = uxBufferLength; - uxSourceBytesRemaining = uxBufferLength; + /* Parse the DNS message header. Map the byte stream onto a structure + * for easier access. */ + pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer ); - /* Parse the DNS message header. - MISRA c 2012 rule 11.3 relaxed to make byte by byte traversal easier */ - pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucUDPPayloadBuffer ); - - /* Introduce a do {} while (0) to allow the use of breaks. */ - do - { - size_t uxBytesRead = 0U; - size_t uxResult; + /* Introduce a do {} while (0) to allow the use of breaks. */ + do + { + size_t uxBytesRead = 0U; + size_t uxResult; - /* Start at the first byte after the header. */ - pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] ); - uxSourceBytesRemaining -= sizeof( DNSMessage_t ); + /* Start at the first byte after the header. */ + pucByte = &( pucUDPPayloadBuffer [ sizeof( DNSMessage_t ) ] ); + uxSourceBytesRemaining -= sizeof( DNSMessage_t ); - /* Skip any question records. */ - usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions ); + /* Skip any question records. */ + usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions ); - for( x = 0U; x < usQuestions; x++ ) - { - #if( ipconfigUSE_LLMNR == 1 ) + for( x = 0U; x < usQuestions; x++ ) { - if( x == 0U ) + #if( ipconfigUSE_LLMNR == 1 ) { - pcRequestedName = ( char * ) pucByte; + if( x == 0U ) + { + pcRequestedName = ( char * ) pucByte; + } } - } - #endif + #endif #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 ) + if( x == 0U ) { - return dnsPARSE_ERROR; + 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; } - uxBytesRead += uxResult; - pucByte = &( pucByte[ uxResult ] ); - uxSourceBytesRemaining -= uxResult; - } - else + 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 ) { - return dnsPARSE_ERROR; + /* 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; } - uxBytesRead += uxResult; - pucByte = &( pucByte[ uxResult ] ); - uxSourceBytesRemaining -= uxResult; - } - /* Check the remaining buffer size. */ - if( uxSourceBytesRemaining >= sizeof( uint32_t ) ) - { - #if( ipconfigUSE_LLMNR == 1 ) + /* Check the remaining buffer size. */ + if( uxSourceBytesRemaining >= sizeof( uint32_t ) ) { - /* usChar2u16 returns value in host endianness. */ - usType = usChar2u16( pucByte ); - usClass = usChar2u16( &( pucByte[ 2 ] ) ); - } - #endif /* ipconfigUSE_LLMNR */ + #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 ); + /* Skip the type and class fields. */ + pucByte = &( pucByte[ sizeof( uint32_t ) ] ); + uxSourceBytesRemaining -= sizeof( uint32_t ); + } + else + { + xReturn = pdFALSE; + break; + } } - else + + if( xReturn == pdFALSE ) { - return dnsPARSE_ERROR; + /* No need to proceed. Break out of the do-while loop. */ + break; } - } - /* Search through the answer records. */ - pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers ); + /* 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++ ) + if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS ) { - BaseType_t xDoAccept; - - uxResult = prvSkipNameField( pucByte, - uxSourceBytesRemaining ); - - /* Check for a malformed response. */ - if( uxResult == 0U ) + const uint16_t usCount = ( uint16_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY; + uint16_t usNumARecordsStored = 0; + + for( x = 0U; ( x < pxDNSMessageHeader->usAnswers ) && ( usNumARecordsStored < usCount ); x++ ) { - return dnsPARSE_ERROR; - } + 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; + 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 ); + /* 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 ) ) + if( usType == ( uint16_t ) dnsTYPE_A_HOST ) { - xDoAccept = pdTRUE; + if( uxSourceBytesRemaining >= ( sizeof( DNSAnswerRecord_t ) + ipSIZE_OF_IPv4_ADDRESS ) ) + { + xDoAccept = pdTRUE; + } + else + { + xDoAccept = pdFALSE; + } } else { + /* Unknown host type. */ 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 ) ) + if( xDoAccept != pdFALSE ) { - /* 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 ) + /* 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 ) ) { - /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */ - if( xDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ) != pdFALSE ) + /* 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 ) { - /* This device has requested this DNS look-up. - The result may be stored in the DNS cache. */ - xDoStore = pdTRUE; + /* 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 ) + #endif /* ipconfigDNS_USE_CALLBACKS == 1 */ + #if( ipconfigUSE_DNS_CACHE == 1 ) { - ( void ) prvProcessDNSCache( pcName, &ulIPAddress, pxDNSAnswerRecord->ulTTL, pdFALSE ); + 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" ) ); } - - /* 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 */ } - #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 ) + 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 ); + pucByte = &( pucByte[ sizeof( DNSAnswerRecord_t ) ] ); + uxSourceBytesRemaining -= sizeof( DNSAnswerRecord_t ); - /* Determine the length of the answer data from the header. */ - usDataLength = FreeRTOS_ntohs( pxDNSAnswerRecord->usDataLength ); + /* 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; + /* Jump over the answer. */ + if( uxSourceBytesRemaining >= usDataLength ) + { + pucByte = &( pucByte[ usDataLength ] ); + uxSourceBytesRemaining -= usDataLength; + } + else + { + /* Malformed response. */ + xReturn = pdFALSE; + break; + } } else { - /* Malformed response. */ - return dnsPARSE_ERROR; + /* Do nothing */ } } - 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 ) + else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) && ( pcRequestedName != NULL ) ) { - 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 ) ) + /* If this is not a reply to our DNS request, it might an LLMNR + request. */ + if( xApplicationDNSQueryHook( &( pcRequestedName[ 1 ] ) ) != pdFALSE ) { - 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 ); + int16_t usLength; + NetworkBufferDescriptor_t *pxNewBuffer = NULL; + NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer ); + LLMNRAnswer_t *pxAnswer; + uint8_t *pucNewBuffer = NULL; - pxNetworkBuffer = pxNewBuffer; - pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ); - - pucByte = &( pucNewBuffer[ xOffset1 ] ); - pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] ); - pxDNSMessageHeader = ipPOINTER_CAST( DNSMessage_t *, pucNewBuffer ); - } - else + if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { - /* Just to indicate that the message may not be answered. */ - pxNetworkBuffer = NULL; - } - } + size_t uxDataLength = uxBufferLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); - /* The test on 'pucNewBuffer' is only to satisfy lint. */ - if( ( pxNetworkBuffer != NULL ) && ( pucNewBuffer != NULL ) ) - { - pxAnswer = ipPOINTER_CAST( LLMNRAnswer_t *, pucByte ); + /* Set the size of the outgoing packet. */ + pxNetworkBuffer->xDataLength = uxDataLength; + pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, uxDataLength + sizeof( LLMNRAnswer_t ) ); - /* 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 */ + if( pxNewBuffer != NULL ) + { + BaseType_t xOffset1, xOffset2; - pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; - pxAnswer->ucNameOffset = ( uint8_t ) ( pcRequestedName - ( char * ) pucNewBuffer ); + xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer ); + xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer ); - #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 ) ); + pxNetworkBuffer = pxNewBuffer; + pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ); - prvReplyDNSMessage( pxNetworkBuffer, usLength ); + 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; + } + } - if( pxNewBuffer != NULL ) + /* The test on 'pucNewBuffer' is only to satisfy lint. */ + if( ( pxNetworkBuffer != NULL ) && ( pucNewBuffer != NULL ) ) { - vReleaseNetworkBufferAndDescriptor( pxNewBuffer ); + 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. */ - } + 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 ) ); diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c index 9fc53fa76..efb1348d1 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c @@ -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 ) - { - /* 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; - - /* 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 + /* Are there IP-options. */ + if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER ) { - /* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying - IP-options will be dropped. */ - return eReleaseBuffer; + /* 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; + + /* 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 } - #endif - } - /* Add the IP and MAC addresses to the ARP table if they are not - already there - otherwise refresh the age of the existing - entry. */ - if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP ) - { - /* Refresh the ARP cache with the IP/MAC-address of the received - packet. For UDP packets, this will be done later in - xProcessReceivedUDPPacket(), as soon as it's know that the message - will be handled. This will prevent the ARP cache getting - overwritten with the IP address of useless broadcast packets. */ - vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress ); - } - switch( ucProtocol ) - { - case ipPROTOCOL_ICMP : - /* The IP packet contained an ICMP frame. Don't bother checking - the ICMP checksum, as if it is wrong then the wrong data will - also be returned, and the source of the ping will know something - went wrong because it will not be able to validate what it - receives. */ - #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) + if( eReturn != eReleaseBuffer ) + { + /* 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 ) + /* 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 ) ) ) { - pcType = "UDP"; + usChecksum = ipINVALID_LENGTH; + location = 2; + break; } - #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ - } - else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) - { - if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) ) + usLength = pxIPPacket->xIPHeader.usLength; + usLength = FreeRTOS_ntohs( usLength ); + if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) ) { usChecksum = ipINVALID_LENGTH; - location = 5; - goto error_exit; + location = 3; + break; } - pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.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 ) { - pcType = "TCP"; + if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER ) ) + { + usChecksum = ipINVALID_LENGTH; + location = 4; + break; + } + + pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) ); + #if( ipconfigHAS_DEBUG_PRINTF != 0 ) + { + pcType = "UDP"; + } + #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ } - #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 ) ) + else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) { - usChecksum = ipINVALID_LENGTH; - location = 6; - goto error_exit; - } + if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER ) ) + { + usChecksum = ipINVALID_LENGTH; + location = 5; + break; + } - pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) ); - #if( ipconfigHAS_DEBUG_PRINTF != 0 ) + 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( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) + if( uxBufferLength < ( uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER ) ) { - pcType = "ICMP"; + usChecksum = ipINVALID_LENGTH; + location = 6; + break; } - else + + pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) ); + #if( ipconfigHAS_DEBUG_PRINTF != 0 ) { - pcType = "IGMP"; + if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) + { + pcType = "ICMP"; + } + else + { + pcType = "IGMP"; + } } + #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ + } + else + { + /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */ + usChecksum = ipUNHANDLED_PROTOCOL; + location = 7; + break; } - #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 ) + /* The protocol and checksum field have been identified. Check the direction + of the packet. */ + if( xOutgoingPacket != pdFALSE ) { - /* 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 ) + /* 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 ) { - static BaseType_t xCount = 0; - - if( xCount < 5 ) + /* 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 ) { - FreeRTOS_printf( ( "usGenerateProtocolChecksum: UDP packet from %xip without CRC dropped\n", - FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) ); - xCount++; + 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 /* ( ipconfigHAS_PRINTF != 0 ) */ + #endif + location = 8; + break; } - #else + else { - /* Sender hasn't set the checksum, no use to calculate it. */ - usChecksum = ipCORRECT_CRC; + /* Other incoming packet than UDP. */ } - #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 */ + 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 ) + if( ( ulLength < ( ( uint32_t ) sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ) || + ( ulLength > ( ( uint32_t ) ipconfigNETWORK_MTU - ( uint32_t ) uxIPHeaderLength ) ) ) { - FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) ); - } - #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ + #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 ) ); + /* 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. */ - } + /* 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 ) + if( xOutgoingPacket == pdFALSE ) { - usChecksum = ( uint16_t )ipCORRECT_CRC; + /* 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 ) ) + else { - /* 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( ( usChecksum == 0U ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) ) { - if( xOutgoingPacket != pdFALSE ) + /* 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 ) { - FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) ); + if( xOutgoingPacket != pdFALSE ) + { + FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) ); + } } - } - #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ + #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ - usChecksum = ( uint16_t )0xffffu; + usChecksum = ( uint16_t )0xffffu; + } } - } - usChecksum = FreeRTOS_htons( usChecksum ); + 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 */ - - error_exit: + 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; diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c index d960088e0..b2aa187e8 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c @@ -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 + diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c index f827175ec..de1dd5ca3 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c @@ -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; diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h index c0ae4ed10..cef40d899 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h @@ -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 diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h index fc0dc4683..5aeecaf93 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h @@ -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_. diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h index 0b0cfed0f..7dd369023 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_dump_packets.h @@ -1,4 +1,29 @@ /* + * 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. */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h index f20cef4d9..d07956f4a 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/tcp_mem_stats.h @@ -1,4 +1,29 @@ /* + * 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 */ |