diff --git a/source/FreeRTOS_DHCP.c b/source/FreeRTOS_DHCP.c index 6bca3e1708..0a2500d2e1 100644 --- a/source/FreeRTOS_DHCP.c +++ b/source/FreeRTOS_DHCP.c @@ -209,14 +209,21 @@ uint8_t * pucUDPPayload = NULL; const DHCPMessage_IPv4_t * pxDHCPMessage; int32_t lBytes; + struct freertos_sockaddr xSourceAddress; + BaseType_t xFristIter = pdTRUE; + + memset( &xSourceAddress, 0, sizeof( xSourceAddress ) ); while( EP_DHCPData.xDHCPSocket != NULL ) { BaseType_t xRecvFlags = FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK; NetworkEndPoint_t * pxIterator = NULL; + struct freertos_sockaddr xSourceAddressCurrent; + socklen_t xSourceAddressCurrentLength = 0; + pucUDPPayload = NULL; /* Peek the next UDP message. */ - lBytes = FreeRTOS_recvfrom( EP_DHCPData.xDHCPSocket, &( pucUDPPayload ), 0, xRecvFlags, NULL, NULL ); + lBytes = FreeRTOS_recvfrom( EP_DHCPData.xDHCPSocket, &( pucUDPPayload ), 0, xRecvFlags, &xSourceAddressCurrent, &xSourceAddressCurrentLength ); if( lBytes < ( ( int32_t ) sizeof( DHCPMessage_IPv4_t ) ) ) { @@ -225,9 +232,20 @@ FreeRTOS_printf( ( "vDHCPProcess: FreeRTOS_recvfrom returns %d\n", ( int ) lBytes ) ); } + if( ( lBytes >= 0 ) && ( pucUDPPayload != NULL ) ) + { + FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayload ); + } + break; } + if( xFristIter == pdTRUE ) + { + memcpy( &xSourceAddress, &xSourceAddressCurrent, xSourceAddressCurrentLength ); + xFristIter = pdFALSE; + } + /* Map a DHCP structure onto the received data. */ /* MISRA Ref 11.3.1 [Misaligned access] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ @@ -239,10 +257,12 @@ { pxIterator = pxNetworkEndPoints; - /* Find the end-point with given transaction ID. */ + /* Find the end-point with given transaction ID and verify DHCP server address. */ while( pxIterator != NULL ) { - if( pxDHCPMessage->ulTransactionID == FreeRTOS_htonl( pxIterator->xDHCPData.ulTransactionId ) ) + if( ( pxDHCPMessage->ulTransactionID == FreeRTOS_htonl( pxIterator->xDHCPData.ulTransactionId ) ) && + ( ( xSourceAddress.sin_address.ulIP_IPv4 == xSourceAddressCurrent.sin_address.ulIP_IPv4 ) && + ( xSourceAddress.sin_port == xSourceAddressCurrent.sin_port ) ) ) { break; } diff --git a/source/FreeRTOS_DHCPv6.c b/source/FreeRTOS_DHCPv6.c index 978fa395d3..bddb34a4ff 100644 --- a/source/FreeRTOS_DHCPv6.c +++ b/source/FreeRTOS_DHCPv6.c @@ -421,14 +421,21 @@ void vDHCPv6Process( BaseType_t xReset, BaseType_t lBytes; size_t uxLength; + struct freertos_sockaddr xSourceAddress; + BaseType_t xFristIter = pdTRUE; + + memset( &xSourceAddress, 0, sizeof( xSourceAddress ) ); for( ; ; ) { BaseType_t xResult; BaseType_t xRecvFlags = ( BaseType_t ) FREERTOS_ZERO_COPY; + struct freertos_sockaddr xSourceAddressCurrent; + socklen_t xSourceAddressCurrentLength = 0; + pucUDPPayload = NULL; /* Get the next UDP message. */ - lBytes = FreeRTOS_recvfrom( EP_DHCPData.xDHCPSocket, &( pucUDPPayload ), 0, xRecvFlags, NULL, NULL ); + lBytes = FreeRTOS_recvfrom( EP_DHCPData.xDHCPSocket, &( pucUDPPayload ), 0, xRecvFlags, &xSourceAddressCurrent, &xSourceAddressCurrentLength ); if( lBytes <= 0 ) { @@ -437,19 +444,39 @@ void vDHCPv6Process( BaseType_t xReset, FreeRTOS_printf( ( "vDHCPProcess: FreeRTOS_recvfrom returns %d\n", ( int ) lBytes ) ); } + if( ( lBytes == 0 ) && ( pucUDPPayload != NULL ) ) + { + FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayload ); + } + break; } - uxLength = ( size_t ) lBytes; + if( xFristIter == pdTRUE ) + { + memcpy( &xSourceAddress, &xSourceAddressCurrent, sizeof( xSourceAddress ) ); + xFristIter = pdFALSE; + } + + /* Verify DHCPv6 server address. */ + if( ( memcmp( &( xSourceAddress.sin_address.xIP_IPv6.ucBytes ), \ + &( xSourceAddressCurrent.sin_address.xIP_IPv6.ucBytes ), \ + sizeof( xSourceAddressCurrent.sin_address.xIP_IPv6.ucBytes ) ) == 0 ) && + ( xSourceAddress.sin_port == xSourceAddressCurrent.sin_port ) ) + { + uxLength = ( size_t ) lBytes; - xResult = prvDHCPv6Analyse( pxEndPoint, pucUDPPayload, uxLength, &( xDHCPMessage ) ); + xResult = prvDHCPv6Analyse( pxEndPoint, pucUDPPayload, uxLength, &( xDHCPMessage ) ); - FreeRTOS_printf( ( "prvDHCPv6Analyse: %s\n", ( xResult == pdPASS ) ? "Pass" : "Fail" ) ); + FreeRTOS_printf( ( "prvDHCPv6Analyse: %s\n", ( xResult == pdPASS ) ? "Pass" : "Fail" ) ); - if( xResult == pdPASS ) - { - xDoProcess = xDHCPv6Process_PassReplyToEndPoint( pxEndPoint ); + if( xResult == pdPASS ) + { + xDoProcess = xDHCPv6Process_PassReplyToEndPoint( pxEndPoint ); + } } + + FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayload ); } } diff --git a/test/cbmc/proofs/DHCPv6/DHCPv6Process/DHCPv6Process_harness.c b/test/cbmc/proofs/DHCPv6/DHCPv6Process/DHCPv6Process_harness.c index 980c620853..1e988a2fd7 100644 --- a/test/cbmc/proofs/DHCPv6/DHCPv6Process/DHCPv6Process_harness.c +++ b/test/cbmc/proofs/DHCPv6/DHCPv6Process/DHCPv6Process_harness.c @@ -153,6 +153,16 @@ int32_t FreeRTOS_recvfrom( Socket_t xSocket, return retVal; } +/* For the purpose of this proof we stub the + * implementation of FreeRTOS_ReleaseUDPPayloadBuffer here, but make sure that + * the pvBuffer is not NULL, its not verified here if the pointer is a valid + * payload buffer as its proved in other proofs */ +void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer ) +{ + __CPROVER_assert( pvBuffer != NULL, + "FreeRTOS precondition: pvBuffer != NULL" ); +} + void harness() { BaseType_t xReset; diff --git a/test/cbmc/proofs/DHCPv6/DHCPv6Process/Makefile.json b/test/cbmc/proofs/DHCPv6/DHCPv6Process/Makefile.json index 5a2d345cb4..af189b335a 100644 --- a/test/cbmc/proofs/DHCPv6/DHCPv6Process/Makefile.json +++ b/test/cbmc/proofs/DHCPv6/DHCPv6Process/Makefile.json @@ -5,6 +5,7 @@ "CBMCFLAGS": [ "--unwind {LOOP_UNWIND_COUNT}", + "--unwindset memcmp.0:17", "--nondet-static --flush" ], "OPT": diff --git a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c index c3a2dd4e83..6bf31d2ab9 100644 --- a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c +++ b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c @@ -41,6 +41,8 @@ static int32_t ulGenericLength; static NetworkBufferDescriptor_t * pxGlobalNetworkBuffer[ 10 ]; static uint8_t GlobalBufferCounter = 0; +struct freertos_sockaddr xSourceAddress, xSourceAddress2; + static uint8_t pucUDPBuffer[ xSizeofUDPBuffer ]; static uint8_t DHCP_header[] = @@ -346,6 +348,16 @@ static int32_t FreeRTOS_recvfrom_ResetAndIncorrectStateWithSocketAlreadyCreated_ *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } + if( pxSourceAddress != NULL ) + { + memcpy( pxSourceAddress, &xSourceAddress, sizeof( xSourceAddress ) ); + } + + if( pxSourceAddressLength != NULL ) + { + *pxSourceAddressLength = sizeof( xSourceAddress ); + } + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; @@ -355,6 +367,55 @@ static int32_t FreeRTOS_recvfrom_ResetAndIncorrectStateWithSocketAlreadyCreated_ return xSizeofUDPBuffer; } +static int32_t FreeRTOS_recvfrom_LoopedCall( const ConstSocket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + NetworkEndPoint_t * pxIterator = pxNetworkEndPoints; + size_t xSizeRetBufferSize = xSizeofUDPBuffer; + + if( callbacks == 2 ) + { + pxNetworkEndPoints->xDHCPData.eDHCPState = eInitialWait; + } + else if( callbacks == 4 ) + { + xSizeRetBufferSize = 200; + } + + if( ( xFlags & FREERTOS_ZERO_COPY ) != 0 ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + if( pxSourceAddress != NULL ) + { + if( callbacks == 2 ) + { + xSourceAddress2.sin_port = 6060; + } + + memcpy( pxSourceAddress, &xSourceAddress2, sizeof( xSourceAddress2 ) ); + } + + if( pxSourceAddressLength != NULL ) + { + *pxSourceAddressLength = sizeof( xSourceAddress2 ); + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( 0x01ABCDEF ); + + return xSizeRetBufferSize; +} + static int32_t FreeRTOS_recvfrom_ResetAndIncorrectStateWithSocketAlreadyCreated_validUDPmessage_TwoFlagOptions_nullbytes( const ConstSocket_t xSocket, void * pvBuffer, size_t uxBufferLength, diff --git a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c index 3ae1718e9f..e586ea2db6 100644 --- a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c +++ b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c @@ -341,6 +341,12 @@ void test_vDHCPProcess_ResetAndIncorrectStateWithSocketAlreadyCreated( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); + + /* Ignore the source address and source address + * length argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); + /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make random number generation pass. */ @@ -420,6 +426,9 @@ void test_vDHCPProcess_CorrectStateDHCPHookFailsDHCPSocketNonNULL( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); + /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that the user indicates anything else than the desired options. */ @@ -467,8 +476,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookDefaultReturn( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -511,8 +524,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNotNULLButGNW /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -549,8 +566,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNotNULLButHos /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -621,8 +642,14 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsNoBroadcast( v /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -669,8 +696,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsNoBroadcast_NU /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -718,8 +749,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsUseBroadCast( /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -768,8 +803,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendSucceedsUseBroadCas /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -819,8 +858,12 @@ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendSucceedsUseBroadCas /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that the user indicates anything else than the desired options. */ eStubExpectedDHCPPhase = eDHCPPhasePreDiscover; pxStubExpectedEndPoint = pxEndPoint; @@ -866,8 +909,12 @@ void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWFails( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Return NULL network buffer. */ @@ -883,6 +930,38 @@ void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWFails( void ) TEST_ASSERT_EQUAL( eSendDHCPRequest, pxEndPoint->xDHCPData.eDHCPState ); } +void test_vDHCPProcess_RecvFromReturnsTimeout( void ) +{ + struct xSOCKET xTestSocket; + NetworkEndPoint_t xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; + + /* This should remain unchanged. */ + xDHCPv4Socket = &xTestSocket; + xDHCPSocketUserCount = 1; + pxEndPoint->xDHCPData.xDHCPSocket = &xTestSocket; + /* Put the required state. */ + pxEndPoint->xDHCPData.eDHCPState = eSendDHCPRequest; + pxEndPoint->xDHCPData.eExpectedState = eSendDHCPRequest; + + /* Expect these arguments. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, -pdFREERTOS_ERRNO_EAGAIN ); + + /* Ignore the buffer, source address and source address + * length argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Return NULL network buffer. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + xSocketValid_ExpectAnyArgsAndReturn( pdFALSE ); + + vDHCPProcess( pdFALSE, pxEndPoint ); +} + + void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendFails( void ) { struct xSOCKET xTestSocket; @@ -898,8 +977,12 @@ void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendFails( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ @@ -936,8 +1019,12 @@ void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendSucceeds( void /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ @@ -978,8 +1065,12 @@ void test_vDHCPProcess_eWaitingOfferRecvfromFailsNoTimeout( void ) /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - pxEndPoint->xDHCPData.xDHCPTxTime ) > pxEndPoint->xDHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ @@ -1014,7 +1105,13 @@ void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutGiveUp( void ) /* prvClo /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the source address and source address + * length argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); + + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - pxEndPoint->xDHCPData.xDHCPTxTime ) > pxEndPoint->xDHCPData.xDHCPTxPeriod */ @@ -1066,8 +1163,12 @@ void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGFail( void /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - pxEndPoint->xDHCPData.xDHCPTxTime ) > pxEndPoint->xDHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ @@ -1109,8 +1210,12 @@ void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassUseBroa /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - pxEndPoint->xDHCPData.xDHCPTxTime ) > pxEndPoint->xDHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ @@ -1162,8 +1267,12 @@ void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassNoBroad /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPv4Socket, NULL, 0UL, FREERTOS_ZERO_COPY + FREERTOS_MSG_PEEK, NULL, NULL, 0 ); - /* Ignore the buffer argument though. */ + + /* Ignore the buffer, source address and source address + * length argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddress(); + FreeRTOS_recvfrom_IgnoreArg_pxSourceAddressLength(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - pxEndPoint->xDHCPData.xDHCPTxTime ) > pxEndPoint->xDHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ @@ -1235,6 +1344,97 @@ void test_vDHCPProcess_eLeasedAddress_CorrectState_ValidBytesInMessage( void ) TEST_ASSERT_EQUAL( eLeasedAddress, pxEndPoint->xDHCPData.eDHCPState ); } +/** + *@brief This test function ensures that when the DHCP states are mismatching after + * initial parsing of response from DHCP server, if a new response from a different DHCP + * server will cause a infinite loop inside the vDHCPProcess. + */ +void test_vDHCPProcess_eLeasedAddress_InCorrectState_Loop( void ) +{ + struct xSOCKET xTestSocket; + NetworkEndPoint_t xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; + uint8_t * pucUDPPayload; + + /* This should remain unchanged. */ + xDHCPv4Socket = &xTestSocket; + xDHCPSocketUserCount = 1; + pxEndPoint->xDHCPData.xDHCPSocket = &xTestSocket; + /* Put the required state. */ + pxEndPoint->xDHCPData.eDHCPState = eLeasedAddress; + pxEndPoint->xDHCPData.eExpectedState = eLeasedAddress; + pxEndPoint->xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Make sure that the local IP address is uninitialised. */ + pxEndPoint->ipv4_settings.ulIPAddress = 0; + /* Put a verifiable value. */ + memset( &pxEndPoint->ipv4_settings, 0xAA, sizeof( IPV4Parameters_t ) ); + /* Put a verifiable value. */ + memset( &pxEndPoint->ipv4_defaults, 0xBB, sizeof( IPV4Parameters_t ) ); + + pxNetworkEndPoints = pxEndPoint; + + /* Expect these arguments. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_LoopedCall ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + FreeRTOS_IsEndPointUp_IgnoreAndReturn( pdFALSE ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); + + vDHCPProcess( pdFALSE, pxEndPoint ); + + TEST_ASSERT_EQUAL( eInitialWait, pxEndPoint->xDHCPData.eDHCPState ); +} + +/** + *@brief This test function ensures after initial parsing of response from + * DHCP server, if a new response arrives for a different endpoint rather than + * the one with which vDHCPProcess was initially called with. + */ +void test_vDHCPProcess_eLeasedAddress_InCorrectState_Loop2( void ) +{ + struct xSOCKET xTestSocket; + NetworkEndPoint_t xEndPoint = { 0 }, xEndPoint2 = { 0 }, * pxEndPoint = &xEndPoint; + uint8_t * pucUDPPayload; + + /* This should remain unchanged. */ + xDHCPv4Socket = &xTestSocket; + xDHCPSocketUserCount = 1; + pxEndPoint->xDHCPData.xDHCPSocket = &xTestSocket; + /* Put the required state. */ + pxEndPoint->xDHCPData.eDHCPState = eLeasedAddress; + pxEndPoint->xDHCPData.eExpectedState = eLeasedAddress; + pxEndPoint->xDHCPData.ulTransactionId = 0x01ABCDFF; + + xEndPoint2.xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Make sure that the local IP address is uninitialised. */ + pxEndPoint->ipv4_settings.ulIPAddress = 0; + /* Put a verifiable value. */ + memset( &pxEndPoint->ipv4_settings, 0xAA, sizeof( IPV4Parameters_t ) ); + /* Put a verifiable value. */ + memset( &pxEndPoint->ipv4_defaults, 0xBB, sizeof( IPV4Parameters_t ) ); + + pxNetworkEndPoints = pxEndPoint; + pxEndPoint->pxNext = &xEndPoint2; + xEndPoint2.xDHCPData.eDHCPState = eWaitingOffer; + xEndPoint2.xDHCPData.eExpectedState = eInitialWait; + + /* Expect these arguments. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_LoopedCall ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + FreeRTOS_IsEndPointUp_IgnoreAndReturn( pdFALSE ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); + + vDHCPProcess( pdFALSE, pxEndPoint ); + + TEST_ASSERT_EQUAL( eInitialWait, pxEndPoint->xDHCPData.eDHCPState ); +} + void test_vDHCPProcess_eLeasedAddress_CorrectState_ValidBytesInMessage_TransactionIDMismatch( void ) { struct xSOCKET xTestSocket; diff --git a/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_stubs.c b/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_stubs.c index 1e3a4e3830..a216126be5 100644 --- a/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_stubs.c +++ b/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_stubs.c @@ -69,6 +69,12 @@ extern Socket_t xDHCPv6Socket; eTestStubsOperation_t eTestStubsOperation = eTestStubsOperationNone; +#define xSizeofUDPBuffer 300 + +static uint8_t pucUDPBuffer[ xSizeofUDPBuffer ]; + +struct freertos_sockaddr xSourceAddress; + static uint8_t ucTestDHCPv6TransactionID[] = { 0x12, 0x34, 0x56 }; static uint8_t ucTestDHCPv6OptionClientID[] = { 0x00, 0x01, 0x00, 0x01, 0xC7, 0x92, 0xBC, 0x80, 0x12, 0x11, 0x22, 0x33, 0x44, 0x22 }; @@ -499,3 +505,149 @@ void vPortEnterCritical( void ) void vPortExitCritical( void ) { } + +int32_t FreeRTOS_recvfrom_DHCPv6_LoopedCall( const ConstSocket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + NetworkEndPoint_t * pxIterator = pxNetworkEndPoints; + size_t xSizeRetBufferSize = xSizeofUDPBuffer; + + if( callbacks == 1 ) + { + pxNetworkEndPoints->xDHCPData.eDHCPState = eInitialWait; + } + else if( callbacks == 2 ) + { + xSizeRetBufferSize = -pdFREERTOS_ERRNO_EAGAIN; + } + + if( ( xFlags & FREERTOS_ZERO_COPY ) != 0 ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + if( pxSourceAddress != NULL ) + { + if( callbacks == 0 ) + { + memset( &xSourceAddress.sin_address.xIP_IPv6.ucBytes, 0xAB, sizeof( xSourceAddress.sin_address.xIP_IPv6.ucBytes ) ); + xSourceAddress.sin_port = 6060; + } + + if( callbacks == 1 ) + { + memset( &xSourceAddress.sin_address.xIP_IPv6.ucBytes, 0xAD, sizeof( xSourceAddress.sin_address.xIP_IPv6.ucBytes ) ); + xSourceAddress.sin_port = 6060; + } + + memcpy( pxSourceAddress, &xSourceAddress, sizeof( xSourceAddress ) ); + } + + if( pxSourceAddressLength != NULL ) + { + *pxSourceAddressLength = sizeof( xSourceAddress ); + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( 0x01ABCDEF ); + + return xSizeRetBufferSize; +} + +int32_t FreeRTOS_recvfrom_DHCPv6_LoopedCall_DifferentPort( const ConstSocket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + NetworkEndPoint_t * pxIterator = pxNetworkEndPoints; + size_t xSizeRetBufferSize = xSizeofUDPBuffer; + + if( callbacks == 1 ) + { + pxNetworkEndPoints->xDHCPData.eDHCPState = eInitialWait; + } + else if( callbacks == 2 ) + { + xSizeRetBufferSize = -pdFREERTOS_ERRNO_EAGAIN; + } + + if( ( xFlags & FREERTOS_ZERO_COPY ) != 0 ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + if( pxSourceAddress != NULL ) + { + if( callbacks == 0 ) + { + memset( &xSourceAddress.sin_address.xIP_IPv6.ucBytes, 0xAD, sizeof( xSourceAddress.sin_address.xIP_IPv6.ucBytes ) ); + xSourceAddress.sin_port = 6060; + } + else if( callbacks == 1 ) + { + memset( &xSourceAddress.sin_address.xIP_IPv6.ucBytes, 0xAD, sizeof( xSourceAddress.sin_address.xIP_IPv6.ucBytes ) ); + xSourceAddress.sin_port = 5050; + } + + memcpy( pxSourceAddress, &xSourceAddress, sizeof( xSourceAddress ) ); + } + + if( pxSourceAddressLength != NULL ) + { + *pxSourceAddressLength = sizeof( xSourceAddress ); + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( 0x01ABCDEF ); + + return xSizeRetBufferSize; +} + + +int32_t FreeRTOS_recvfrom_DHCPv6_ReturnZero( const ConstSocket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + NetworkEndPoint_t * pxIterator = pxNetworkEndPoints; + size_t xSizeRetBufferSize = 0; + + if( ( xFlags & FREERTOS_ZERO_COPY ) != 0 ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + if( pxSourceAddress != NULL ) + { + memcpy( pxSourceAddress, &xSourceAddress, sizeof( xSourceAddress ) ); + } + + if( pxSourceAddressLength != NULL ) + { + *pxSourceAddressLength = sizeof( xSourceAddress ); + } + + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( 0x01ABCDEF ); + + return xSizeRetBufferSize; +} diff --git a/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_utest.c b/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_utest.c index aa44055356..a144885cbe 100644 --- a/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_utest.c +++ b/test/unit-test/FreeRTOS_DHCPv6/FreeRTOS_DHCPv6_utest.c @@ -1598,6 +1598,7 @@ void test_vDHCPv6Process_AdvertiseHappyPath() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -1646,6 +1647,7 @@ void test_vDHCPv6Process_AdvertiseIATA() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 93 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -1694,6 +1696,7 @@ void test_vDHCPv6Process_ReplyHappyPath() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -1904,6 +1907,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_UnknownMsgType() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -1944,6 +1948,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_WrongTransactionID() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -1984,6 +1989,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_ReadTransactionIDError() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2024,6 +2030,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_ReadOptionError() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2064,6 +2071,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_LackServerID() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 126 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2104,6 +2112,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_ExtraOptionValue32() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 150 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2152,6 +2161,7 @@ void test_vDHCPv6Process_prvDHCPv6Analyse_BitConfigInitError() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 126 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); xBitConfig_init_IgnoreAndReturn( pdFAIL ); @@ -2191,6 +2201,7 @@ void test_vDHCPv6Process_prvIsOptionLengthValid_OptionLessThanMinLength() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 500 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2231,6 +2242,7 @@ void test_vDHCPv6Process_prvIsOptionLengthValid_OptionLargerThanMaxLength() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 500 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2271,6 +2283,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleStatusCode_MessageTooLong() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 71 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2281,6 +2294,133 @@ void test_vDHCPv6Process_prvDHCPv6_handleStatusCode_MessageTooLong() TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } +/** + * @brief Check if vDHCPv6Process can handle packets from a different + * DHCP server while vDHCPv6Process is already processing responses from + * another DHCP server + */ +void test_vDHCPv6Process_DifferentDHCPServerRespondedWhileInProcess() +{ + NetworkEndPoint_t xEndPoint; + DHCPMessage_IPv6_t xDHCPMessage; + struct xSOCKET xLocalDHCPv6Socket; + + memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); + memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); + memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); + + pxNetworkEndPoints = &xEndPoint; + + memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); + memcpy( xEndPoint.ipv6_settings.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); + xEndPoint.ipv6_settings.uxPrefixLength = 64; + xEndPoint.bits.bIPv6 = pdTRUE; + xEndPoint.bits.bWantDHCP = pdTRUE; + + xEndPoint.xDHCPData.eDHCPState = eWaitingOffer; + xEndPoint.xDHCPData.eExpectedState = eWaitingOffer; + xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; + xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; + memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); + + xEndPoint.pxDHCPMessage = &xDHCPMessage; + + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_DHCPv6_LoopedCall ); + xTaskGetTickCount_IgnoreAndReturn( 0 ); + FreeRTOS_ReleaseUDPPayloadBuffer_ExpectAnyArgs(); + FreeRTOS_ReleaseUDPPayloadBuffer_ExpectAnyArgs(); + + prvPrepareAdvertiseStatusCodeLongMessage(); + + vDHCPv6Process( pdFALSE, &xEndPoint ); + + TEST_ASSERT_EQUAL( eInitialWait, xEndPoint.xDHCPData.eDHCPState ); +} + +/** + * @brief Check if vDHCPv6Process can handle packets from a different + * DHCP server while vDHCPv6Process is already processing responses from + * server running on different port on the same server. + */ +void test_vDHCPv6Process_DifferentPortWhileInProcess() +{ + NetworkEndPoint_t xEndPoint; + DHCPMessage_IPv6_t xDHCPMessage; + struct xSOCKET xLocalDHCPv6Socket; + + memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); + memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); + memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); + + pxNetworkEndPoints = &xEndPoint; + + memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); + memcpy( xEndPoint.ipv6_settings.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); + xEndPoint.ipv6_settings.uxPrefixLength = 64; + xEndPoint.bits.bIPv6 = pdTRUE; + xEndPoint.bits.bWantDHCP = pdTRUE; + + xEndPoint.xDHCPData.eDHCPState = eWaitingOffer; + xEndPoint.xDHCPData.eExpectedState = eWaitingOffer; + xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; + xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; + memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); + + xEndPoint.pxDHCPMessage = &xDHCPMessage; + + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_DHCPv6_LoopedCall_DifferentPort ); + xTaskGetTickCount_IgnoreAndReturn( 0 ); + FreeRTOS_ReleaseUDPPayloadBuffer_ExpectAnyArgs(); + FreeRTOS_ReleaseUDPPayloadBuffer_ExpectAnyArgs(); + + prvPrepareAdvertiseStatusCodeLongMessage(); + + vDHCPv6Process( pdFALSE, &xEndPoint ); + + TEST_ASSERT_EQUAL( eInitialWait, xEndPoint.xDHCPData.eDHCPState ); +} + + +/** + * @brief Check if vDHCPv6Process FreeRTOS_recvfrom returns 0 + */ +void test_vDHCPv6Process_RecvFromReturnsZero() +{ + NetworkEndPoint_t xEndPoint; + DHCPMessage_IPv6_t xDHCPMessage; + struct xSOCKET xLocalDHCPv6Socket; + + memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); + memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); + memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); + + pxNetworkEndPoints = &xEndPoint; + + memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); + memcpy( xEndPoint.ipv6_settings.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); + xEndPoint.ipv6_settings.uxPrefixLength = 64; + xEndPoint.bits.bIPv6 = pdTRUE; + xEndPoint.bits.bWantDHCP = pdTRUE; + + xEndPoint.xDHCPData.eDHCPState = eWaitingOffer; + xEndPoint.xDHCPData.eExpectedState = eWaitingOffer; + xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; + xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; + memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); + + xEndPoint.pxDHCPMessage = &xDHCPMessage; + + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_DHCPv6_ReturnZero ); + xTaskGetTickCount_IgnoreAndReturn( 0 ); + FreeRTOS_ReleaseUDPPayloadBuffer_ExpectAnyArgs(); + + prvPrepareAdvertiseStatusCodeLongMessage(); + + vDHCPv6Process( pdFALSE, &xEndPoint ); + + TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); +} + /** * @brief Receive the message when global endpoint list is empty. */ @@ -2309,6 +2449,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_EmptyEndpointList() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2397,6 +2538,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_MultipleEndpoints() memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2446,6 +2588,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerDUIDT memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2489,6 +2632,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerLengt memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 100 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2532,6 +2676,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerLengt memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 100 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2576,6 +2721,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerDUID( memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2630,6 +2776,7 @@ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentEndpoint() memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2779,6 +2926,7 @@ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_WithDNS() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 122 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2823,6 +2971,7 @@ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_ManyDNS() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 154 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2868,6 +3017,7 @@ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_ShortLeaseTime() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2913,6 +3063,7 @@ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_CustomLeaseTime() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -2957,6 +3108,7 @@ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleAdvertise_HookFailure() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); @@ -2999,6 +3151,7 @@ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleAdvertise_HookDefault() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookUseDefault ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); @@ -3605,6 +3758,7 @@ void test_vDHCPv6Process_ReplyInvalidLengthIANA() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3645,6 +3799,7 @@ void test_vDHCPv6Process_ReplyInvalidLengthIAPD() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3685,6 +3840,7 @@ void test_vDHCPv6Process_ReplyInvalidSubOptionIANA() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3725,6 +3881,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_ClientLengthTooSmall() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3765,6 +3922,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_ClientLengthTooBig() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3805,18 +3963,21 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_WrongClientID() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDLengthWrong(); vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDPeekFalse(); vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDContentWrong(); @@ -3855,6 +4016,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_ServerLengthTooSmall() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3895,6 +4057,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_ServerLengthTooBig() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3935,6 +4098,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_InvalidDNSLength() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3943,6 +4107,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_InvalidDNSLength() vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -3983,6 +4148,7 @@ void test_vDHCPv6Process_prvDHCPv6_handleOption_DomainSearchList() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 108 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); @@ -4058,6 +4224,7 @@ void test_vDHCPv6Process_AdvertiseStatusFail() xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 123 ); + FreeRTOS_ReleaseUDPPayloadBuffer_Ignore(); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 );