diff --git a/source/FreeRTOS_DNS_Parser.c b/source/FreeRTOS_DNS_Parser.c index 01d2075b63..9570fac308 100644 --- a/source/FreeRTOS_DNS_Parser.c +++ b/source/FreeRTOS_DNS_Parser.c @@ -486,31 +486,30 @@ LLMNRAnswer_t * pxAnswer; uint8_t * pucNewBuffer = NULL; size_t uxExtraLength; + size_t uxDataLength = uxBufferLength + + sizeof( UDPHeader_t ) + + sizeof( EthernetHeader_t ) + + uxIPHeaderSizePacket( pxNetworkBuffer ); - if( xBufferAllocFixedSize == pdFALSE ) - { - size_t uxDataLength = uxBufferLength + - sizeof( UDPHeader_t ) + - sizeof( EthernetHeader_t ) + - uxIPHeaderSizePacket( pxNetworkBuffer ); - - #if ( ipconfigUSE_IPv6 != 0 ) - if( xSet.usType == dnsTYPE_AAAA_HOST ) - { - uxExtraLength = sizeof( LLMNRAnswer_t ) + ipSIZE_OF_IPv6_ADDRESS - sizeof( pxAnswer->ulIPAddress ); - } - else - #endif /* ( ipconfigUSE_IPv6 != 0 ) */ - #if ( ipconfigUSE_IPv4 != 0 ) - { - uxExtraLength = sizeof( LLMNRAnswer_t ); - } - #else /* ( ipconfigUSE_IPv4 != 0 ) */ + #if ( ipconfigUSE_IPv6 != 0 ) + if( xSet.usType == dnsTYPE_AAAA_HOST ) { - /* do nothing, coverity happy */ + uxExtraLength = sizeof( LLMNRAnswer_t ) + ipSIZE_OF_IPv6_ADDRESS - sizeof( pxAnswer->ulIPAddress ); } - #endif /* ( ipconfigUSE_IPv4 != 0 ) */ + else + #endif /* ( ipconfigUSE_IPv6 != 0 ) */ + #if ( ipconfigUSE_IPv4 != 0 ) + { + uxExtraLength = sizeof( LLMNRAnswer_t ); + } + #else /* ( ipconfigUSE_IPv4 != 0 ) */ + { + /* do nothing, coverity happy */ + } + #endif /* ( ipconfigUSE_IPv4 != 0 ) */ + if( xBufferAllocFixedSize == pdFALSE ) + { /* Set the size of the outgoing packet. */ pxNetworkBuffer->xDataLength = uxDataLength; pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, @@ -539,7 +538,17 @@ } else { - pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] ); + /* When xBufferAllocFixedSize is TRUE, check if the buffer size is big enough to + * store the answer. */ + if( ( uxDataLength + uxExtraLength ) <= ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) + { + pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] ); + } + else + { + /* Just to indicate that the message may not be answered. */ + pxNetworkBuffer = NULL; + } } if( ( pxNetworkBuffer != NULL ) ) @@ -1214,7 +1223,11 @@ { /* BufferAllocation_1.c is used, the Network Buffers can contain at least * ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER. */ - configASSERT( uxSizeNeeded < ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ); + if( uxSizeNeeded > ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) + { + /* The buffer is too small to reply. Drop silently. */ + break; + } } pxNetworkBuffer->xDataLength = uxSizeNeeded; diff --git a/source/portable/BufferManagement/BufferAllocation_1.c b/source/portable/BufferManagement/BufferAllocation_1.c index 55ac667ecd..dfb0ba0f44 100644 --- a/source/portable/BufferManagement/BufferAllocation_1.c +++ b/source/portable/BufferManagement/BufferAllocation_1.c @@ -237,11 +237,8 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS BaseType_t xInvalid = pdFALSE; UBaseType_t uxCount; - /* The current implementation only has a single size memory block, so - * the requested size parameter is not used (yet). */ - ( void ) xRequestedSizeBytes; - - if( xNetworkBufferSemaphore != NULL ) + if( ( xNetworkBufferSemaphore != NULL ) && + ( xRequestedSizeBytes <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) ) { /* If there is a semaphore available, there is a network buffer * available. */ @@ -432,10 +429,18 @@ UBaseType_t uxGetNumberOfFreeNetworkBuffers( void ) NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes ) { - /* In BufferAllocation_1.c all network buffer are allocated with a - * maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the - * network buffer. */ - pxNetworkBuffer->xDataLength = xNewSizeBytes; + if( xNewSizeBytes <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) + { + /* In BufferAllocation_1.c all network buffer are allocated with a + * maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the + * network buffer. */ + pxNetworkBuffer->xDataLength = xNewSizeBytes; + } + else + { + pxNetworkBuffer = NULL; + } + return pxNetworkBuffer; } diff --git a/test/cbmc/proofs/DNS/DNSTreatNBNS/DNS_TreatNBNS_harness.c b/test/cbmc/proofs/DNS/DNSTreatNBNS/DNS_TreatNBNS_harness.c index 54d13c4d6f..cea7f57f53 100644 --- a/test/cbmc/proofs/DNS/DNSTreatNBNS/DNS_TreatNBNS_harness.c +++ b/test/cbmc/proofs/DNS/DNSTreatNBNS/DNS_TreatNBNS_harness.c @@ -122,10 +122,7 @@ void harness() BaseType_t xDataSize; - /* When re-adjusting the buffer, (sizeof( NBNSAnswer_t ) - 2 * sizeof( uint16_t )) more bytes are - * required to be added to the existing buffer. Make sure total bytes doesn't exceed ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER - * when re-resizing. This will prevent hitting an assert if Buffer Allocation 1 is used. */ - __CPROVER_assume( ( xDataSize != 0 ) && ( xDataSize < ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER - ( sizeof( NBNSAnswer_t ) - 2 * sizeof( uint16_t ) ) ) ) ); + __CPROVER_assume( ( xDataSize > 0 ) && ( xDataSize < ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) ); xNetworkBuffer.pucEthernetBuffer = safeMalloc( xDataSize ); xNetworkBuffer.xDataLength = xDataSize; diff --git a/test/cbmc/proofs/DNS/DNSTreatNBNS/Makefile.json b/test/cbmc/proofs/DNS/DNSTreatNBNS/Makefile.json index dcf186869f..b5ace42526 100644 --- a/test/cbmc/proofs/DNS/DNSTreatNBNS/Makefile.json +++ b/test/cbmc/proofs/DNS/DNSTreatNBNS/Makefile.json @@ -24,6 +24,7 @@ "DEF": [ "ipconfigUSE_DNS_CACHE={USE_CACHE}", - "ipconfigUSE_NBNS=1" + "ipconfigUSE_NBNS=1", + "ipconfigNETWORK_MTU=586" ] } diff --git a/test/cbmc/proofs/DNS_ParseDNSReply/Configurations.json b/test/cbmc/proofs/DNS_ParseDNSReply/Configurations.json index 80f783f4cd..ae8c857026 100644 --- a/test/cbmc/proofs/DNS_ParseDNSReply/Configurations.json +++ b/test/cbmc/proofs/DNS_ParseDNSReply/Configurations.json @@ -1,16 +1,18 @@ { "ENTRY": "DNS_ParseDNSReply", - "TEST_PAYLOAD_SIZE": 2, - "TEST_IPV4_PACKET_SIZE": 29, - "TEST_IPV6_PACKET_SIZE": 49, + "TEST_MAX_TEST_UNWIND_LOOP": 6, + "TEST_MIN_TEST_DNS_HEADER": 12, + "TEST_MIN_IPV4_UDP_PACKET_SIZE": 42, + "TEST_MIN_IPV6_UDP_PACKET_SIZE": 62, + "TEST_IPV4_NETWORK_MTU": "__eval {TEST_MIN_IPV4_UDP_PACKET_SIZE} + {TEST_MIN_TEST_DNS_HEADER} + {TEST_MAX_TEST_UNWIND_LOOP}", + "TEST_IPV6_NETWORK_MTU": "__eval {TEST_MIN_IPV6_UDP_PACKET_SIZE} + {TEST_MIN_TEST_DNS_HEADER} + {TEST_MAX_TEST_UNWIND_LOOP}", "CBMCFLAGS": [ "--unwind 1", - "--unwindset DNS_ParseDNSReply.0:{TEST_PAYLOAD_SIZE}", - "--unwindset DNS_ReadNameField.0:{TEST_PAYLOAD_SIZE}", - "--unwindset DNS_ReadNameField.1:{TEST_PAYLOAD_SIZE}", - "--unwindset parseDNSAnswer.0:{TEST_PAYLOAD_SIZE}", - "--unwindset strncpy.0:{TEST_PAYLOAD_SIZE}" + "--unwindset strlen.0:{TEST_MAX_TEST_UNWIND_LOOP}", + "--unwindset DNS_ParseDNSReply.0:{TEST_MAX_TEST_UNWIND_LOOP}", + "--unwindset DNS_ReadNameField.0:{TEST_MAX_TEST_UNWIND_LOOP}", + "--unwindset DNS_ReadNameField.1:{TEST_MAX_TEST_UNWIND_LOOP}" ], "OPT": [ @@ -25,21 +27,63 @@ "DEF": [ { - "IPv4": + "IPv4_FixedNetworkBufferSize": [ - "TEST_PACKET_SIZE={TEST_IPV4_PACKET_SIZE}", + "TEST_MAX_PAYLOAD_SIZE={TEST_MAX_TEST_UNWIND_LOOP}", "ipconfigUSE_LLMNR=1", "ipconfigUSE_MDNS=1", - "IS_TESTING_IPV6=0" + "IS_TESTING_IPV6=0", + "IS_BUFFER_ALLOCATE_FIXED=1", + "ipconfigNETWORK_MTU={TEST_IPV4_NETWORK_MTU}", + "ipconfigUSE_TCP=0", + "ipconfigUSE_DHCP=0", + "ipconfigTCP_MSS=536", + "ipconfigDNS_CACHE_NAME_LENGTH={TEST_MAX_TEST_UNWIND_LOOP}" ] }, { - "IPv6": + "IPv6_FixedNetworkBufferSize": [ - "TEST_PACKET_SIZE={TEST_IPV6_PACKET_SIZE}", + "TEST_MAX_PAYLOAD_SIZE={TEST_MAX_TEST_UNWIND_LOOP}", "ipconfigUSE_LLMNR=1", "ipconfigUSE_MDNS=1", - "IS_TESTING_IPV6=1" + "IS_TESTING_IPV6=1", + "IS_BUFFER_ALLOCATE_FIXED=1", + "ipconfigNETWORK_MTU={TEST_IPV6_NETWORK_MTU}", + "ipconfigUSE_TCP=0", + "ipconfigUSE_DHCP=0", + "ipconfigTCP_MSS=536", + "ipconfigDNS_CACHE_NAME_LENGTH={TEST_MAX_TEST_UNWIND_LOOP}" + ] + }, + { + "IPv4_DynamicNetworkBufferSize": + [ + "TEST_MAX_PAYLOAD_SIZE={TEST_MAX_TEST_UNWIND_LOOP}", + "ipconfigUSE_LLMNR=1", + "ipconfigUSE_MDNS=1", + "IS_TESTING_IPV6=0", + "IS_BUFFER_ALLOCATE_FIXED=0", + "ipconfigNETWORK_MTU={TEST_IPV4_NETWORK_MTU}", + "ipconfigUSE_TCP=0", + "ipconfigUSE_DHCP=0", + "ipconfigTCP_MSS=536", + "ipconfigDNS_CACHE_NAME_LENGTH={TEST_MAX_TEST_UNWIND_LOOP}" + ] + }, + { + "IPv6_DynamicNetworkBufferSize": + [ + "TEST_MAX_PAYLOAD_SIZE={TEST_MAX_TEST_UNWIND_LOOP}", + "ipconfigUSE_LLMNR=1", + "ipconfigUSE_MDNS=1", + "IS_TESTING_IPV6=1", + "IS_BUFFER_ALLOCATE_FIXED=0", + "ipconfigNETWORK_MTU={TEST_IPV6_NETWORK_MTU}", + "ipconfigUSE_TCP=0", + "ipconfigUSE_DHCP=0", + "ipconfigTCP_MSS=536", + "ipconfigDNS_CACHE_NAME_LENGTH={TEST_MAX_TEST_UNWIND_LOOP}" ] } ], diff --git a/test/cbmc/proofs/DNS_ParseDNSReply/DNS_ParseDNSReply_harness.c b/test/cbmc/proofs/DNS_ParseDNSReply/DNS_ParseDNSReply_harness.c index 9fae89ddc8..60572ef2df 100644 --- a/test/cbmc/proofs/DNS_ParseDNSReply/DNS_ParseDNSReply_harness.c +++ b/test/cbmc/proofs/DNS_ParseDNSReply/DNS_ParseDNSReply_harness.c @@ -10,6 +10,7 @@ /* FreeRTOS+TCP includes. */ #include "FreeRTOS_IP.h" +#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_DNS.h" #include "FreeRTOS_DNS_Parser.h" #include "NetworkBufferManagement.h" @@ -17,7 +18,8 @@ #include "IPTraceMacroDefaults.h" #include "cbmc.h" -#include "../../utility/memory_assignments.c" + +const BaseType_t xBufferAllocFixedSize = IS_BUFFER_ALLOCATE_FIXED; /**************************************************************** * Signature of function under test @@ -60,12 +62,18 @@ NetworkBufferDescriptor_t * pxUDPPayloadBuffer_to_NetworkBuffer( const void * pv uint32_t ulChar2u32( const uint8_t * pucPtr ) { + uint32_t ret; + __CPROVER_assert( __CPROVER_r_ok( pucPtr, 4 ), "must be 4 bytes legal address to read" ); + return ret; } uint16_t usChar2u16( const uint8_t * pucPtr ) { + uint16_t ret; + __CPROVER_assert( __CPROVER_r_ok( pucPtr, 2 ), "must be 2 bytes legal address to read" ); + return ret; } const char * FreeRTOS_inet_ntop( BaseType_t xAddressFamily, @@ -131,11 +139,14 @@ NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( const Networ { NetworkBufferDescriptor_t * pxNetworkBuffer = safeMalloc( sizeof( NetworkBufferDescriptor_t ) ); - if( ensure_memory_is_valid( pxNetworkBuffer, xNewLength ) ) + if( pxNetworkBuffer != NULL ) { pxNetworkBuffer->pucEthernetBuffer = safeMalloc( xNewLength ); - __CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer ); + __CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer != NULL ); pxNetworkBuffer->xDataLength = xNewLength; + + pxNetworkBuffer->pxEndPoint = safeMalloc( sizeof( NetworkEndPoint_t ) ); + __CPROVER_assume( pxNetworkBuffer->pxEndPoint != NULL ); } return pxNetworkBuffer; @@ -176,23 +187,31 @@ void harness() uint8_t * pPayloadBuffer; size_t uxPayloadBufferLength; - __CPROVER_assert( TEST_PACKET_SIZE < CBMC_MAX_OBJECT_SIZE, - "TEST_PACKET_SIZE < CBMC_MAX_OBJECT_SIZE" ); - - __CPROVER_assume( uxBufferLength < CBMC_MAX_OBJECT_SIZE ); - __CPROVER_assume( uxBufferLength <= TEST_PACKET_SIZE ); + __CPROVER_assume( uxBufferLength <= ipconfigNETWORK_MTU ); + __CPROVER_assume( pxNetworkEndPoint_Temp != NULL ); lIsIPv6Packet = IS_TESTING_IPV6; - xNetworkBuffer.pucEthernetBuffer = safeMalloc( uxBufferLength ); - xNetworkBuffer.xDataLength = uxBufferLength; - xNetworkBuffer.pxEndPoint = pxNetworkEndPoint_Temp; + if( xBufferAllocFixedSize != pdFALSE ) + { + /* When xBufferAllocFixedSize is true, buffers in all network descriptors + * is big enough to allow all Ethernet packet. */ + xNetworkBuffer.pucEthernetBuffer = safeMalloc( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ); + xNetworkBuffer.xDataLength = uxBufferLength; + xNetworkBuffer.pxEndPoint = pxNetworkEndPoint_Temp; + } + else + { + xNetworkBuffer.pucEthernetBuffer = safeMalloc( uxBufferLength ); + xNetworkBuffer.xDataLength = uxBufferLength; + xNetworkBuffer.pxEndPoint = pxNetworkEndPoint_Temp; + } __CPROVER_assume( xNetworkBuffer.pucEthernetBuffer != NULL ); if( lIsIPv6Packet ) { - __CPROVER_assume( uxBufferLength >= ulIpv6UdpOffset ); /* 62 is total size of IPv4 UDP header, including ethernet, IPv6, UDP headers. */ + __CPROVER_assume( uxBufferLength >= ulIpv6UdpOffset ); /* 62 is total size of IPv6 UDP header, including ethernet, IPv6, UDP headers. */ pPayloadBuffer = xNetworkBuffer.pucEthernetBuffer + ulIpv6UdpOffset; uxPayloadBufferLength = uxBufferLength - ulIpv6UdpOffset; } diff --git a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/ProcessReceivedTCPPacket_harness.c b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/ProcessReceivedTCPPacket_harness.c index c15387b900..d60cdd6bc9 100644 --- a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/ProcessReceivedTCPPacket_harness.c +++ b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/ProcessReceivedTCPPacket_harness.c @@ -47,8 +47,7 @@ void prvTCPReturnPacket( FreeRTOS_Socket_t * pxSocket, uint32_t ulLen, BaseType_t xReleaseAfterSend ) { - __CPROVER_assert( pxSocket != NULL, "pxSocket should not be NULL" ); - __CPROVER_assert( pxDescriptor != NULL, "pxDescriptor should not be NULL" ); + __CPROVER_assert( pxSocket != NULL || pxDescriptor != NULL, "Either pxSocket or pxDescriptor must be non-NULL" ); __CPROVER_assert( pxDescriptor->pucEthernetBuffer != NULL, "pucEthernetBuffer should not be NULL" ); } @@ -57,11 +56,14 @@ int32_t prvTCPPrepareSend( FreeRTOS_Socket_t * pxSocket, NetworkBufferDescriptor_t ** ppxNetworkBuffer, UBaseType_t uxOptionsLength ) { + int32_t ret = nondet_int32(); + __CPROVER_assert( pxSocket != NULL, "pxSocket cannot be NULL" ); __CPROVER_assert( *ppxNetworkBuffer != NULL, "*ppxNetworkBuffer cannot be NULL" ); __CPROVER_assert( __CPROVER_r_ok( ( *ppxNetworkBuffer )->pucEthernetBuffer, ( *ppxNetworkBuffer )->xDataLength ), "Data in *ppxNetworkBuffer must be readable" ); - return nondet_int32(); + __CPROVER_assume( ret >= 0 && ret <= ipconfigNETWORK_MTU ); + return ret; } /* prvTCPHandleState is proven separately. */ @@ -137,6 +139,7 @@ FreeRTOS_Socket_t * pxTCPSocketLookup( uint32_t ulLocalIP, { /* This test case is for IPv4. */ __CPROVER_assume( xRetSocket->bits.bIsIPv6 == pdFALSE ); + __CPROVER_assume( xRetSocket->u.xTCP.ucPeerWinScaleFactor <= tcpTCP_OPT_WSOPT_MAXIMUM_VALUE ); } return xRetSocket; @@ -151,7 +154,7 @@ NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedS if( pxNetworkBuffer ) { pxNetworkBuffer->pucEthernetBuffer = safeMalloc( xRequestedSizeBytes ); - __CPROVER_assume( pxNetworkBuffer->xDataLength == ipSIZE_OF_ETH_HEADER + sizeof( int32_t ) ); + pxNetworkBuffer->xDataLength = xRequestedSizeBytes; } return pxNetworkBuffer; @@ -174,8 +177,12 @@ size_t uxIPHeaderSizeSocket( const FreeRTOS_Socket_t * pxSocket ) void harness() { NetworkBufferDescriptor_t * pxNetworkBuffer; + size_t tcpPacketSize; + + __CPROVER_assume( tcpPacketSize >= ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + sizeof( TCPHeader_t ) ) ); + + pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( tcpPacketSize, 0 ); - pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( TCPPacket_t ), 0 ); /* To avoid asserting on the network buffer being NULL. */ __CPROVER_assume( pxNetworkBuffer != NULL ); diff --git a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket_IPv6/ProcessReceivedTCPPacket_IPv6_harness.c b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket_IPv6/ProcessReceivedTCPPacket_IPv6_harness.c index 4135a9144f..204d404e44 100644 --- a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket_IPv6/ProcessReceivedTCPPacket_IPv6_harness.c +++ b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket_IPv6/ProcessReceivedTCPPacket_IPv6_harness.c @@ -63,6 +63,7 @@ FreeRTOS_Socket_t * pxTCPSocketLookup( uint32_t ulLocalIP, { /* This test case is for IPv6. */ __CPROVER_assume( xRetSocket->bits.bIsIPv6 == pdTRUE ); + __CPROVER_assume( xRetSocket->u.xTCP.ucPeerWinScaleFactor <= tcpTCP_OPT_WSOPT_MAXIMUM_VALUE ); } return xRetSocket; @@ -101,8 +102,11 @@ void harness() { NetworkBufferDescriptor_t * pxNetworkBuffer; EthernetHeader_t * pxEthernetHeader; + size_t tcpPacketSize; - pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( TCPPacket_IPv6_t ), 0 ); + __CPROVER_assume( tcpPacketSize >= ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( TCPHeader_t ) ) ); + + pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( tcpPacketSize, 0 ); /* To avoid asserting on the ethernet buffer being NULL. */ __CPROVER_assume( pxNetworkBuffer != NULL ); diff --git a/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c b/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c index b2eb963de9..77607346ee 100644 --- a/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c +++ b/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c @@ -995,7 +995,7 @@ void test_DNS_TreatNBNS_Fail_BufferAllocation1( void ) usChar2u16_ExpectAnyArgsAndReturn( dnsNBNS_TYPE_NET_BIOS ); /* usType */ usChar2u16_ExpectAnyArgsAndReturn( dnsNBNS_FLAGS_OPCODE_QUERY ); - catch_assert( DNS_TreatNBNS( pucPayload, uxBufferLength, 1234 ) ); + DNS_TreatNBNS( pucPayload, uxBufferLength, 1234 ); ASSERT_DNS_QUERY_HOOK_CALLED(); } @@ -2853,6 +2853,275 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_new_netbuffer3( void ) ASSERT_DNS_QUERY_HOOK_CALLED(); } +/** + * @brief ensures that when the re-use network buffer is reused when xBufferAllocFixedSize + * is set, then packet is sent over the network. + */ +void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_fixed_buffer( void ) +{ + uint32_t ret; + uint8_t udp_buffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ] = { 0 }; + uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; + size_t uxBufferLength = 250; + struct freertos_addrinfo * pxAddressInfo; + uint16_t usPort = 80; + NetworkEndPoint_t xEndPoint = { 0 }; + + memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); + + xBufferAllocFixedSize = pdTRUE; + + NetworkBufferDescriptor_t pxNetworkBuffer = { 0 }; + xEndPoint.ipv4_settings.ulIPAddress = 0xABCD1234; + pxNetworkBuffer.pucEthernetBuffer = udp_buffer; + pxNetworkBuffer.xDataLength = uxBufferLength; + pxNetworkBuffer.pxEndPoint = &xEndPoint; + + UDPPacket_t * pxUDPPacket; + IPHeader_t * pxIPHeader; + UDPHeader_t * pxUDPHeader; + + pxUDPPacket = ( ( UDPPacket_t * ) + pxNetworkBuffer.pucEthernetBuffer ); + pxIPHeader = &pxUDPPacket->xIPHeader; + pxIPHeader->ucVersionHeaderLength = 0x0; + pxUDPHeader = &pxUDPPacket->xUDPHeader; + IPPacket_t * xIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer.pucEthernetBuffer ); + + pxIPHeader->ulSourceIPAddress = 1234; + + NetworkBufferDescriptor_t pxNewBuffer; + pxNewBuffer.pucEthernetBuffer = udp_buffer; + pxNewBuffer.xDataLength = uxBufferLength; + + BaseType_t xExpected = pdFALSE; + size_t beg = sizeof( DNSMessage_t ); + + DNSMessage_t * dns_header; + + dns_header = ( DNSMessage_t * ) pucUDPPayloadBuffer; + + dns_header->usQuestions = FreeRTOS_htons( 1 ); + dns_header->usAnswers = FreeRTOS_htons( 2 ); + dns_header->usFlags = dnsDNS_PORT; + + pucUDPPayloadBuffer[ beg ] = 38; + beg++; + strcpy( pucUDPPayloadBuffer + beg, "FreeRTOSbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + beg += 38; + + beg += sizeof( uint32_t ); + + pucUDPPayloadBuffer[ beg ] = 38; + beg++; + strcpy( pucUDPPayloadBuffer + beg, "FreeRTOSbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + beg += 38; + + pucUDPPayloadBuffer[ beg ] = 38; + beg++; + strcpy( pucUDPPayloadBuffer + beg, "FreeRTOSbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + beg += 38; + + uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + hook_return = pdTRUE; + pxUDPPayloadBuffer_to_NetworkBuffer_ExpectAnyArgsAndReturn( &pxNetworkBuffer ); + + usGenerateChecksum_ExpectAnyArgsAndReturn( 555 ); + usGenerateProtocolChecksum_ExpectAnyArgsAndReturn( 444 ); + vReturnEthernetFrame_Expect( &pxNetworkBuffer, pdFALSE ); + + ret = DNS_ParseDNSReply( pucUDPPayloadBuffer, + uxBufferLength, + &pxAddressInfo, + xExpected, + usPort ); + + TEST_ASSERT_EQUAL( pdFALSE, ret ); + ASSERT_DNS_QUERY_HOOK_CALLED(); +} + +/** + * @brief ensures that when the re-use network buffer is reused when xBufferAllocFixedSize + * is set, but packet is not sent over the network due to buffer overflow. + */ +void test_DNS_ParseDNSReply_answer_lmmnr_reply_fixed_buffer_full_content( void ) +{ + uint32_t ret; + uint8_t udp_buffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ] = { 0 }; + uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; + /* Maximum UDP payload length is 1500 + 14 - 42 = 1472. */ + size_t uxBufferLength = ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER - ipUDP_PAYLOAD_OFFSET_IPv4; + struct freertos_addrinfo * pxAddressInfo; + uint16_t usPort = 80; + NetworkEndPoint_t xEndPoint = { 0 }; + int i; + + memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); + + xBufferAllocFixedSize = pdTRUE; + + NetworkBufferDescriptor_t pxNetworkBuffer = { 0 }; + xEndPoint.ipv4_settings.ulIPAddress = 0xABCD1234; + pxNetworkBuffer.pucEthernetBuffer = udp_buffer; + pxNetworkBuffer.xDataLength = uxBufferLength; + pxNetworkBuffer.pxEndPoint = &xEndPoint; + + UDPPacket_t * pxUDPPacket; + IPHeader_t * pxIPHeader; + UDPHeader_t * pxUDPHeader; + + pxUDPPacket = ( ( UDPPacket_t * ) + pxNetworkBuffer.pucEthernetBuffer ); + pxIPHeader = &pxUDPPacket->xIPHeader; + pxIPHeader->ucVersionHeaderLength = 0x0; + pxUDPHeader = &pxUDPPacket->xUDPHeader; + IPPacket_t * xIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer.pucEthernetBuffer ); + + pxIPHeader->ulSourceIPAddress = 1234; + + NetworkBufferDescriptor_t pxNewBuffer; + pxNewBuffer.pucEthernetBuffer = udp_buffer; + pxNewBuffer.xDataLength = uxBufferLength; + + BaseType_t xExpected = pdFALSE; + size_t beg = sizeof( DNSMessage_t ); + + DNSMessage_t * dns_header; + + dns_header = ( DNSMessage_t * ) pucUDPPayloadBuffer; + + dns_header->usQuestions = FreeRTOS_htons( 6 ); + dns_header->usAnswers = FreeRTOS_htons( 0 ); + dns_header->usFlags = dnsDNS_PORT; + + /* First 5 queries have maximum length. */ + + /* DNS name field format requirements: + * - First two bits must be zero to indicate real length + * - Maximum length of a single label is 63 bytes (due to first two bits requirement) + * - Total DNS name is set to 254 bytes to match ipconfigDNS_CACHE_NAME_LENGTH + * + * Format breakdown: + * [label1].[label2].[label3].[label4][\0] + * where: + * - label1, label2, label3: 63 bytes each + * - label4: 61 bytes + * - Total: 63 + 63 + 63 + 61 + 4 (length) + 1 (null terminator) = 255 bytes + */ + for( i = 0; i < 5; i++ ) + { + pucUDPPayloadBuffer[ beg ] = 63; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "Fre" ); /* 63 */ + beg += 63; + pucUDPPayloadBuffer[ beg ] = 63; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "Fre" ); /* 63 */ + beg += 63; + pucUDPPayloadBuffer[ beg ] = 63; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "Fre" ); /* 63 */ + beg += 63; + pucUDPPayloadBuffer[ beg ] = 61; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "F" ); /* 61 */ + beg += 61; + pucUDPPayloadBuffer[ beg++ ] = '\0'; + + /* Skip query's type and class. */ + beg += sizeof( uint32_t ); + } + + /* Memory layout of DNS message till here: + * - Header: 12 bytes + * - Query section: (255 + 4) * 5 bytes = 1295 bytes + * - Total used: 1307 bytes + * + * Available space in UDP payload: + * - Total UDP payload: 1472 bytes + * - Used space: 1307 bytes + * - Remaining space: 165 bytes + */ + + /* Last query to fill the remaining 165 bytes. Reserve 4 bytes for type and class fields. + * + * Format breakdown: + * [label1].[label2].[label3][\0] + * where: + * - label1, label2: 63 bytes each + * - label3: 31 bytes + * - Total: 63 + 63 + 31 + 3 (length) + 1 (null terminator) = 161 bytes */ + pucUDPPayloadBuffer[ beg ] = 63; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "Fre" ); /* 63 */ + beg += 63; + pucUDPPayloadBuffer[ beg ] = 63; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFreeRTOSFree" /* 40 */ + "FreeRTOSFreeRTOSFree" /* 60 */ + "Fre" ); /* 63 */ + beg += 63; + pucUDPPayloadBuffer[ beg ] = 31; + beg++; + strcpy( pucUDPPayloadBuffer + beg, + "FreeRTOSFreeRTOSFree" /* 20 */ + "FreeRTOSFre" ); /* 31 */ + beg += 31; + pucUDPPayloadBuffer[ beg++ ] = '\0'; + + /* Skip query's type and class. */ + beg += sizeof( uint32_t ); + + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_AAAA_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); + hook_return = pdTRUE; + pxUDPPayloadBuffer_to_NetworkBuffer_ExpectAnyArgsAndReturn( &pxNetworkBuffer ); + + ret = DNS_ParseDNSReply( pucUDPPayloadBuffer, + uxBufferLength, + &pxAddressInfo, + xExpected, + usPort ); + + TEST_ASSERT_EQUAL( pdFALSE, ret ); + ASSERT_DNS_QUERY_HOOK_CALLED(); +} + /** * @brief ensures that when the number of answers is zero no packet is sent over * the network