/* * FreeRTOS+TCP * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: MIT * * 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 */ /* Include Unity header */ #include "unity.h" /* Include standard libraries */ #include #include #include #include "mock_task.h" #include "mock_list.h" #include "mock_FreeRTOS_Sockets.h" #include "mock_FreeRTOS_IP_Private.h" #include "mock_FreeRTOS_IP_Timers.h" #include "mock_FreeRTOS_IP.h" #include "mock_FreeRTOS_ARP.h" #include "mock_FreeRTOS_BitConfig.h" #include "mock_FreeRTOS_Sockets.h" #include "mock_FreeRTOS_DHCP.h" /*#include "FreeRTOS_IP_stubs.c" */ #include "catch_assert.h" #include "FreeRTOS_DHCPv6.h" #include "FreeRTOS_DHCPv6_stubs.c" /* =========================== EXTERN VARIABLES =========================== */ #define TEST_DHCPV6_IAID ( 0x27fe8f95 ) #define TEST_DHCPv6_DEFAULT_DUID_TYPE ( 1U ) #define TEST_DHCPv6_DIFFERENT_DUID_TYPE ( 2U ) #define TEST_DHCPv6_DEFAULT_DUID_LENGTH ( 14U ) #define TEST_DHCPv6_DIFFERENT_DUID_LENGTH ( 12U ) extern void prvSendDHCPMessage( NetworkEndPoint_t * pxEndPoint ); extern void prvCloseDHCPv6Socket( NetworkEndPoint_t * pxEndPoint ); extern const char * prvStateName( eDHCPState_t eState ); extern BaseType_t prvDHCPv6_subOption( uint16_t usOption, const DHCPOptionSet_t * pxSet, DHCPMessage_IPv6_t * pxDHCPMessage, BitConfig_t * pxMessage ); /* ============================ Unity Fixtures ============================ */ /*! called before each test case */ void setUp( void ) { InitializeUnitTest(); memset( xTestDHCPv6BitOperation, 0, sizeof( xTestDHCPv6BitOperation ) ); ulTestDHCPv6BitOperationWriteIndex = 0; ulTestDHCPv6BitOperationReadIndex = 0; } /*! called after each test case */ void tearDown( void ) { } /* ============================== Test Cases ============================== */ static void vAddBitOperation( eTestDHCPv6BitOperationType_t eType, const void * pvVal, uint32_t ulSize, uint8_t * pucDebugMsg ) { const uint8_t * pucVal; const uint16_t * pusVal; const uint32_t * pulVal; TEST_ASSERT_TRUE( ulTestDHCPv6BitOperationWriteIndex < TEST_DHCPv6_BIT_OPERATION_MAX_NUM ); xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].eOperationType = eType; xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].ulCustomLength = ulSize; switch( eType ) { case eTestDHCPv6BitOperationWrite8: case eTestDHCPv6BitOperationRead8: pucVal = ( uint8_t * ) pvVal; xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].val.ucVal = *pucVal; break; case eTestDHCPv6BitOperationWrite16: case eTestDHCPv6BitOperationRead16: pusVal = ( uint16_t * ) pvVal; xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].val.usVal = *pusVal; break; case eTestDHCPv6BitOperationWrite32: case eTestDHCPv6BitOperationRead32: pulVal = ( uint32_t * ) pvVal; xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].val.ulVal = *pulVal; break; case eTestDHCPv6BitOperationWriteCustom: case eTestDHCPv6BitOperationReadCustom: case eTestDHCPv6BitOperationReadPeek: TEST_ASSERT_LESS_THAN( TEST_DHCPv6_BIT_OPERATION_MAX_SIZE, ulSize ); memcpy( xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].val.ucValCustom, pvVal, ulSize ); break; } TEST_ASSERT_LESS_THAN_size_t( TEST_DHCPv6_BIT_OPERATION_DEBUG_MSG_MAX_SIZE, strlen( pucDebugMsg ) ); strcpy( xTestDHCPv6BitOperation[ ulTestDHCPv6BitOperationWriteIndex ].ucDebugMsg, pucDebugMsg ); ulTestDHCPv6BitOperationWriteIndex++; } static void prvSetBitOperationStub() { xBitConfig_init_Stub( xStubxBitConfig_init ); vBitConfig_write_8_Stub( xStubvBitConfig_write_8 ); vBitConfig_write_16_Stub( xStubvBitConfig_write_16 ); vBitConfig_write_32_Stub( xStubvBitConfig_write_32 ); vBitConfig_write_uc_Stub( xStubvBitConfig_write_uc ); pucBitConfig_peek_last_index_uc_Stub( xStubpucBitConfig_peek_last_index_uc ); vBitConfig_release_Ignore(); ucBitConfig_read_8_Stub( xStubucBitConfig_read_8 ); usBitConfig_read_16_Stub( xStubusBitConfig_read_16 ); ulBitConfig_read_32_Stub( xStubulBitConfig_read_32 ); xBitConfig_read_uc_Stub( xStubxBitConfig_read_uc ); } static void prvAddMsgHeader( BaseType_t xIsWrite, uint8_t ucMessageType ) { uint8_t ucVal; if( xIsWrite == pdTRUE ) { /* Provide the message type and transaction ID for DHCPv6. */ ucVal = ucMessageType; vAddBitOperation( eTestDHCPv6BitOperationWrite8, &ucVal, 1, "Type" ); vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, ucTestDHCPv6TransactionID, 3, "TransactionID" ); } else { /* Provide the message type and transaction ID for DHCPv6. */ ucVal = ucMessageType; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "Type" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestDHCPv6TransactionID, 3, "TransactionID" ); } } static void prvAddOptionClient( BaseType_t xIsWrite ) { uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* Option Client ID */ usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionClientID" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionClientIDLength" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionClientIDHWType" ); /* Client ID - Time Stamp */ ulVal = ulApplicationTimeHook() - SECS_FROM_1970_TILL_2000; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionClientIDTimeStamp" ); /* Client ID - MAC Address */ vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, ucDefaultMACAddress, ipMAC_ADDRESS_LENGTH_BYTES, "OptionClientIDMAC" ); } else { usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLength" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDHWType" ); /* Client ID - remain ID */ vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucTestDHCPv6OptionClientID[ 4 ], sizeof( ucTestDHCPv6OptionClientID ) - 4, "OptionClientIDRemain" ); } /* Call peek function to compare client ID */ vAddBitOperation( eTestDHCPv6BitOperationReadPeek, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ), "OptionClientIDPeek" ); } static void prvAddOptionServer( BaseType_t xIsWrite, BaseType_t xIsDifferentType, BaseType_t xIsDifferentLength, BaseType_t xIsDifferentID ) { uint16_t usVal; uint32_t ulVal; uint8_t ucDifferentServerID[] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }; if( xIsWrite == pdTRUE ) { /* Option Server ID */ usVal = DHCPv6_Option_Server_Identifier; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionServerID" ); usVal = xIsDifferentLength == pdTRUE ? TEST_DHCPv6_DIFFERENT_DUID_LENGTH : TEST_DHCPv6_DEFAULT_DUID_LENGTH; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionServerIDLength" ); /* Server ID - DUID & hardware Type */ usVal = xIsDifferentType == pdTRUE ? TEST_DHCPv6_DIFFERENT_DUID_TYPE : TEST_DHCPv6_DEFAULT_DUID_TYPE; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionServerIDDUIDType" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionServerIDHWType" ); /* Server ID - remain ID */ if( xIsDifferentID == pdFALSE ) { vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ), "OptionServerIDRemain" ); } else { vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, ucDifferentServerID, sizeof( ucDifferentServerID ), "OptionServerIDRemain" ); } } else { /* Option Server ID */ usVal = DHCPv6_Option_Server_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerID" ); usVal = xIsDifferentLength == pdTRUE ? TEST_DHCPv6_DIFFERENT_DUID_LENGTH : TEST_DHCPv6_DEFAULT_DUID_LENGTH; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDLength" ); /* Server ID - DUID & hardware Type */ usVal = xIsDifferentType == pdTRUE ? TEST_DHCPv6_DIFFERENT_DUID_TYPE : TEST_DHCPv6_DEFAULT_DUID_TYPE; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDDUIDType" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDHWType" ); /* Server ID - remain ID */ if( xIsDifferentID == pdFALSE ) { vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ), "OptionServerIDRemain" ); } else { vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucDifferentServerID, sizeof( ucDifferentServerID ), "OptionServerIDRemain" ); } } } static void prvAddOptionElapsedTime( BaseType_t xIsWrite ) { uint16_t usVal; if( xIsWrite == pdTRUE ) { /* Option Elapsed Time */ usVal = DHCPv6_Option_Elapsed_Time; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionElapsed" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionElapsedLength" ); usVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionElapsedValue" ); } else { /* Option Elapsed Time */ usVal = DHCPv6_Option_Elapsed_Time; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionElapsed" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionElapsedLength" ); usVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionElapsedValue" ); } } static void prvAddOptionIA_Prefix( BaseType_t xIsWrite ) { uint8_t ucVal; uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* Option IA_Prefix */ usVal = DHCPv6_Option_IA_Prefix; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_Prefix" ); usVal = 25U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_PrefixLength" ); /* Preferred Life Time */ ulVal = 4500U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_PrefixPreferLifeTime" ); /* Valid Life Time */ ulVal = 7200U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_PrefixValidLifeTime" ); /* Prefix length */ ucVal = 64U; vAddBitOperation( eTestDHCPv6BitOperationWrite8, &ucVal, 1, "OptionIA_PrefixPrefixLength" ); /* Prefix */ vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, xDefaultNetPrefix.ucBytes, ipSIZE_OF_IPv6_ADDRESS, "OptionIA_PrefixAddress" ); } else { /* Option IA_Prefix */ usVal = DHCPv6_Option_IA_Prefix; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_Prefix" ); usVal = 25U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_PrefixLength" ); /* Preferred Life Time */ ulVal = 4500U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PrefixPreferLifeTime" ); /* Valid Life Time */ ulVal = 7200U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PrefixValidLifeTime" ); /* Prefix length */ ucVal = 64U; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "OptionIA_PrefixPrefixLength" ); /* Prefix */ vAddBitOperation( eTestDHCPv6BitOperationReadCustom, xDefaultNetPrefix.ucBytes, ipSIZE_OF_IPv6_ADDRESS, "OptionIA_PrefixAddress" ); } } static void prvAddOptionIA_PD( BaseType_t xIsWrite ) { uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* Option IA_PD */ usVal = DHCPv6_Option_IA_for_Prefix_Delegation; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_PD" ); usVal = 41U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_PDLength" ); ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_PDIAID" ); ulVal = 3600U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_PDT1" ); ulVal = 5400U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_PDT2" ); } else { /* Option IA_PD */ usVal = DHCPv6_Option_IA_for_Prefix_Delegation; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_PD" ); usVal = 41U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_PDLength" ); ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDIAID" ); ulVal = 3600U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDT1" ); ulVal = 5400U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDT2" ); } /* Add sub-option IA-Prefix */ prvAddOptionIA_Prefix( xIsWrite ); } static void prvAddOptionIA_NA( BaseType_t xIsWrite, uint16_t usLength ) { uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* Option IA_NA */ usVal = DHCPv6_Option_NonTemporaryAddress; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_NA" ); usVal = usLength; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_NALength" ); ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_NAIAID" ); /* T1 */ ulVal = 4500U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_NAT1" ); /* T2 */ ulVal = 7200U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_NAT2" ); } else { /* Option IA_NA */ usVal = DHCPv6_Option_NonTemporaryAddress; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NA" ); usVal = usLength; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NALength" ); ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_NAIAID" ); /* T1 */ ulVal = 4500U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_NAT1" ); /* T2 */ ulVal = 7200U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_NAT2" ); } } static void prvAddOptionIA_TA( BaseType_t xIsWrite ) { uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* IA_TA */ usVal = DHCPv6_Option_TemporaryAddress; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_TA" ); usVal = 4U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_TALength" ); /* Code will use xBitConfig_read_uc to drop all messages in option IA_TA */ ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, &ulVal, 4, "OptionIA_TAIAID" ); } else { /* IA_TA */ usVal = DHCPv6_Option_TemporaryAddress; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_TA" ); usVal = 4U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_TALength" ); /* Code will use xBitConfig_read_uc to drop all messages in option IA_TA */ ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ulVal, 4, "OptionIA_TAIAID" ); } } static void prvAddOptionIAAddress( BaseType_t xIsWrite ) { uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* IA_NA sub-option IA Address */ usVal = DHCPv6_Option_IA_Address; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_NASubIAAddress" ); usVal = 24U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionIA_NASubIAAddressLength" ); vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS, "OptionIA_NASubIAAddressIP" ); /* Preferred Life Time */ ulVal = 900U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_NASubIAAddressPreferLifeTime" ); /* Valid Life Time */ ulVal = 900U; vAddBitOperation( eTestDHCPv6BitOperationWrite32, &ulVal, 4, "OptionIA_NASubIAAddressValidLifeTime" ); } else { /* IA_NA sub-option IA Address */ usVal = DHCPv6_Option_IA_Address; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubIAAddress" ); usVal = 24U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubIAAddressLength" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS, "OptionIA_NASubIAAddressIP" ); /* Preferred Life Time */ ulVal = 900U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_NASubIAAddressPreferLifeTime" ); /* Valid Life Time */ ulVal = 900U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_NASubIAAddressValidLifeTime" ); } } static void prvAddOptionStatusCode( BaseType_t xIsWrite ) { const uint8_t ucStatusCodeSuccess[] = "success"; uint16_t usVal; uint32_t ulVal; if( xIsWrite == pdTRUE ) { /* Status Code */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionSubStatus" ); usVal = 9U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionSubStatusLength" ); usVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionStatusValue" ); /* Status message */ vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, ucStatusCodeSuccess, sizeof( ucStatusCodeSuccess ), "OptionStatusMessage" ); } else { /* Status Code */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatus" ); usVal = 9U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusLength" ); usVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusValue" ); /* Status message */ vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucStatusCodeSuccess, sizeof( ucStatusCodeSuccess ), "OptionStatusMessage" ); } } static void prvAddOptionPreference( BaseType_t xIsWrite ) { uint8_t ucVal; uint16_t usVal; if( xIsWrite == pdTRUE ) { /* Option Preference */ usVal = DHCPv6_Option_Preference; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionPreference" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionPreferenceLength" ); /* Put 0 as preference value */ ucVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationWrite8, &ucVal, 1, "OptionPreferenceValue" ); } else { /* Option Preference */ usVal = DHCPv6_Option_Preference; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionPreference" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionPreferenceLength" ); /* Put 0 as preference value */ ucVal = 0U; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "OptionPreferenceValue" ); } } static void prvAddOptionList( BaseType_t xIsWrite ) { uint16_t usVal; if( xIsWrite == pdTRUE ) { /* Option List */ usVal = DHCPv6_Option_Option_List; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionList" ); usVal = 4U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionListLength" ); usVal = DHCP6_OPTION_REQUEST_DNS; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionListDNS" ); usVal = DHCP6_OPTION_REQUEST_DOMAIN_SEARCH_LIST; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionListDomainSearchList" ); } else { /* Option List */ usVal = DHCPv6_Option_Option_List; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionList" ); usVal = 4U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionListLength" ); usVal = DHCP6_OPTION_REQUEST_DNS; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionListDNS" ); usVal = DHCP6_OPTION_REQUEST_DOMAIN_SEARCH_LIST; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionListDomainSearchList" ); } } static void prvAddOptionDNSServer( BaseType_t xIsWrite, uint8_t ucDNSNum ) { uint16_t usVal; int i; TEST_ASSERT_LESS_OR_EQUAL( 3, ucDNSNum ); if( xIsWrite == pdTRUE ) { /* Option DNS recursive name server */ usVal = DHCPv6_Option_DNS_recursive_name_server; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionDNSRecursiveNameServer" ); usVal = 16U * ucDNSNum; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionDNSRecursiveNameServerLength" ); for( i = 0; i < ucDNSNum; i++ ) { vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, &xDNSAddress[ i ], sizeof( IPv6_Address_t ), "OptionDNSInfo" ); } } else { /* Option DNS recursive name server */ usVal = DHCPv6_Option_DNS_recursive_name_server; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDNSRecursiveNameServer" ); usVal = 16U * ucDNSNum; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDNSRecursiveNameServerLength" ); for( i = 0; i < ucDNSNum; i++ ) { vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &xDNSAddress[ i ], sizeof( IPv6_Address_t ), "OptionDNSInfo" ); } } } static void prvAddOptionDomainSearchList( BaseType_t xIsWrite ) { uint16_t usVal; uint8_t ucValCustom[ 2 ]; if( xIsWrite == pdTRUE ) { /* Option DNS recursive name server */ usVal = DHCPv6_Option_Domain_Search_List; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionDomainSearchList" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationWrite16, &usVal, 2, "OptionDomainSearchListLength" ); vAddBitOperation( eTestDHCPv6BitOperationWriteCustom, &ucValCustom, 2, "OptionDomainSearchListValue" ); } else { /* Option DNS recursive name server */ usVal = DHCPv6_Option_Domain_Search_List; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDomainSearchList" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDomainSearchListLength" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucValCustom, 2, "OptionDomainSearchListValue" ); } } /** * @brief Prepare function calls for sending DHCPv6 solicitation message. */ static void prvPrepareSolicitation() { prvSetBitOperationStub(); prvAddMsgHeader( pdTRUE, DHCPv6_message_Type_Solicit ); prvAddOptionClient( pdTRUE ); prvAddOptionElapsedTime( pdTRUE ); prvAddOptionIA_PD( pdTRUE ); prvAddOptionIA_NA( pdTRUE, 12U ); } /** * @brief Prepare buffer content as DHCPv6 advertise. */ static void prvPrepareAdvertise() { /* We hard code the option sequence in advertise message. * 1. Client ID * 2. Server ID * 3. IA_NA * - Sub-option IA Address * - Sub-option IA Prefix * - Sub-option Status Code * 4. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); prvAddOptionIA_NA( pdFALSE, 82U ); /* Add IA_Address as sub-option in IA_NA */ prvAddOptionIAAddress( pdFALSE ); /* Add IA_Prefix as sub-option in IA_NA */ prvAddOptionIA_Prefix( pdFALSE ); /* Add Status code as sub-option in IA_NA */ prvAddOptionStatusCode( pdFALSE ); /* Add Status code as option */ prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 advertise with IA_TA option. */ static void prvPrepareAdvertiseIATA() { /* We hard code the option sequence in advertise message. * 1. Client ID * 2. Server ID * 3. IA_TA - not implemented, ignored * 4. IA_PD */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); prvAddOptionIA_TA( pdFALSE ); prvAddOptionIA_PD( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 advertise without server ID. */ static void prvPrepareAdvertiseNoServerID() { /* We hard code the option sequence in advertise message. * 1. Client ID * 2. IA_NA * - Sub-option IA Address * - Sub-option IA Prefix * - Sub-option Status Code * 3. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); prvAddOptionClient( pdFALSE ); prvAddOptionIA_NA( pdFALSE, 82U ); /* Add IA_Address as sub-option in IA_NA */ prvAddOptionIAAddress( pdFALSE ); /* Add IA_Prefix as sub-option in IA_NA */ prvAddOptionIA_Prefix( pdFALSE ); /* Add Status code as sub-option in IA_NA */ prvAddOptionStatusCode( pdFALSE ); /* Add Status code as option */ prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 advertise. */ static void prvPrepareAdvertiseSubStatusCodeFail() { /* We hard code the option sequence in advertise message. * 1. Client ID * 2. Server ID * 3. IA_NA * - Sub-option IA Address * - Sub-option IA Prefix * - Sub-option Status Code * 4. Status Code * 5. Preference */ uint16_t usVal; uint8_t usStatusFail[] = "Fail"; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); prvAddOptionIA_NA( pdFALSE, 79U ); /* Add IA_Address as sub-option in IA_NA */ prvAddOptionIAAddress( pdFALSE ); /* Add IA_Prefix as sub-option in IA_NA */ prvAddOptionIA_Prefix( pdFALSE ); /* Add Status code as sub-option in IA_NA */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubStatus" ); usVal = 6U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubStatusLength" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubStatusValue" ); /* Status message */ vAddBitOperation( eTestDHCPv6BitOperationReadCustom, usStatusFail, sizeof( usStatusFail ), "OptionIA_NASubStatusMessage" ); } /** * @brief Prepare function calls for sending DHCPv6 request message. */ static void prvPrepareRequest() { /* We hard code the option sequence in request message. * 1. Client ID * 2. Server ID * 3. Option List * 4. Elapsed Time * 5. IA_PD * 6. IA_NA * 7. DNS Server List */ prvSetBitOperationStub(); prvAddMsgHeader( pdTRUE, DHCPv6_message_Type_Request ); prvAddOptionClient( pdTRUE ); prvAddOptionServer( pdTRUE, pdFALSE, pdFALSE, pdFALSE ); prvAddOptionList( pdTRUE ); prvAddOptionElapsedTime( pdTRUE ); prvAddOptionIA_PD( pdTRUE ); prvAddOptionIA_NA( pdTRUE, 12U ); prvAddOptionDNSServer( pdTRUE, 0 ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReply() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID * 3. IA_NA * - Sub-option IA Address * 4. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); prvAddOptionIA_NA( pdFALSE, 40U ); /* IA_NA sub-option IA Address */ prvAddOptionIAAddress( pdFALSE ); prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Append 1 DNS server info to reply message. */ static void prvPrepareReplyWithDomainSearchList() { prvPrepareReply(); prvAddOptionDomainSearchList( pdFALSE ); } /** * @brief Append 1 DNS server info to reply message. */ static void prvPrepareReplyWithDNS() { prvPrepareReply(); prvAddOptionDNSServer( pdFALSE, 1 ); } /** * @brief Append 3 DNS servers info ( more than ipconfigENDPOINT_DNS_ADDRESS_COUNT ) to reply message. */ static void prvPrepareReplyWithMultipleDNS() { prvPrepareReply(); prvAddOptionDNSServer( pdFALSE, 3 ); } /** * @brief Prepare buffer content as DHCPv6 reply with different server DUID type. */ static void prvPrepareReplyDifferentServerDUIDType() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID with different DUID type * 3. IA_NA * - Sub-option IA Address * 4. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdTRUE, pdFALSE, pdFALSE ); prvAddOptionIA_NA( pdFALSE, 40U ); /* IA_NA sub-option IA Address */ prvAddOptionIAAddress( pdFALSE ); prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 reply with different server DUID type. */ static void prvPrepareReplyDifferentServerLength() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID with different DUID length * 3. IA_NA * - Sub-option IA Address * 4. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdTRUE, pdFALSE ); prvAddOptionIA_NA( pdFALSE, 40U ); /* IA_NA sub-option IA Address */ prvAddOptionIAAddress( pdFALSE ); prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 reply with different server DUID. */ static void prvPrepareReplyDifferentServerDUID() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID with different DUID * 3. IA_NA * - Sub-option IA Address * 4. Status Code * 5. Preference */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdTRUE ); prvAddOptionIA_NA( pdFALSE, 40U ); /* IA_NA sub-option IA Address */ prvAddOptionIAAddress( pdFALSE ); prvAddOptionStatusCode( pdFALSE ); prvAddOptionPreference( pdFALSE ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyInvalidIA_NA() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID * 3. IA_NA - with invalid sub-option length */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); /* IA_NA with invalid sub-option length */ prvAddOptionIA_NA( pdFALSE, 14U ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyInvalidIA_NASubOption() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID * 3. IA_NA - with invalid sub-option */ uint16_t usVal; uint8_t ucValCustom[ 2 ]; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); /* IA_NA with invalid sub-option */ prvAddOptionIA_NA( pdFALSE, 42U ); /* IA_NA sub-option unknown */ usVal = 0xFF; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubInvalid" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubInvalidLength" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucValCustom, 2, "OptionIA_NASubInvalidValue" ); /* IA_NA sub-option IA address with invalid length */ usVal = DHCPv6_Option_IA_Address; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubIAAddress" ); usVal = 20U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_NASubIAAddressLength" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyInvalidIA_PD() { /* We hard code the option sequence in reply message. * 1. Client ID * 2. Server ID * 3. IA_PD - with invalid sub-option length */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionClient( pdFALSE ); prvAddOptionServer( pdFALSE, pdFALSE, pdFALSE, pdFALSE ); /* Option IA_PD with invalid sub-option length */ usVal = DHCPv6_Option_IA_for_Prefix_Delegation; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_PD" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionIA_PDLength" ); ulVal = TEST_DHCPV6_IAID; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDIAID" ); ulVal = 3600U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDT1" ); ulVal = 5400U; vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "OptionIA_PDT2" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyClientIDTooSmall() { /* We hard code the option sequence in reply message. * 1. Client ID with length too small */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLengthSmall" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyClientIDTooBig() { /* We hard code the option sequence in reply message. * 1. Client ID with length too small */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 256U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLengthBig" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDHWType" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyClientIDLengthWrong() { /* We hard code the option sequence in reply message. * 1. Client ID with length too small */ uint16_t usVal; uint32_t ulVal; uint8_t ucValCustom[ 12 ]; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 16U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLength" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDHWType" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucValCustom, 12, "OptionClientIDRemainBig" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyClientIDPeekFalse() { /* We hard code the option sequence in reply message. * 1. Client ID with length too small */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLength" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDHWType" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucTestDHCPv6OptionClientID[ 4 ], sizeof( ucTestDHCPv6OptionClientID ) - 4, "OptionClientIDRemain" ); /* Call peek function to compare client ID */ vAddBitOperation( eTestDHCPv6BitOperationReadPeek, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ), "OptionClientIDPeekFalse" ); vAddBitOperation( eTestDHCPv6BitOperationReturnFalse, NULL, 0, "" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyClientIDContentWrong() { /* We hard code the option sequence in reply message. * 1. Client ID with length too small */ uint16_t usVal; uint32_t ulVal; uint8_t ucWrongClientID[] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 }; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLength" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDHWType" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &ucWrongClientID[ 4 ], sizeof( ucWrongClientID ) - 4, "OptionClientIDRemain" ); /* Call peek function to compare client ID */ vAddBitOperation( eTestDHCPv6BitOperationReadPeek, ucWrongClientID, sizeof( ucWrongClientID ), "OptionClientIDPeek" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyServerIDTooSmall() { /* We hard code the option sequence in reply message. * 1. Server ID with length too small */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Server_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerID" ); usVal = 2U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDLengthSmall" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyServerIDTooBig() { /* We hard code the option sequence in reply message. * 1. Server ID with length too small */ uint16_t usVal; uint32_t ulVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); usVal = DHCPv6_Option_Server_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerID" ); usVal = 256U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDLengthBig" ); /* Client ID - DUID & hardware Type */ usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDDUIDType" ); vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionServerIDHWType" ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyDNSLengthZero() { /* We hard code the option sequence in reply message. * 1. DNS info with 0 length */ prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); prvAddOptionDNSServer( pdFALSE, 0 ); } /** * @brief Prepare buffer content as DHCPv6 reply. */ static void prvPrepareReplyDNSLengthNotAllow() { /* We hard code the option sequence in reply message. * 1. DNS info with 1 length (length must be a multiple of 16) */ uint16_t usVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Reply ); /* Option DNS recursive name server */ usVal = DHCPv6_Option_DNS_recursive_name_server; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDNSRecursiveNameServer" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionDNSRecursiveNameServerValue" ); } /** * @brief Prepare buffer content with known message type. */ static void prvPrepareUnknownMsgType() { prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, 0xEE ); } /** * @brief Prepare buffer content with different transaction ID. */ static void prvPrepareWrongTransactionID() { uint8_t ucVal; uint8_t ucTestInvalidDHCPv6TransactionID[] = { 0x65, 0x43, 0x21 }; prvSetBitOperationStub(); /* Provide the message type and transaction ID for DHCPv6. */ ucVal = DHCPv6_message_Type_Advertise; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "TypeAdvertise" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestInvalidDHCPv6TransactionID, 3, "InvalidTransactionID" ); } /** * @brief Prepare buffer content with transaction ID then set the error bit. */ static void prvPrepareErrorTransactionID() { uint8_t ucVal; prvSetBitOperationStub(); /* Provide the message type and transaction ID for DHCPv6. */ ucVal = DHCPv6_message_Type_Advertise; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "TypeAdvertise" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestDHCPv6TransactionID, 3, "TransactionID" ); vAddBitOperation( eTestDHCPv6BitOperationSetError, 0, 0, "SetError" ); } /** * @brief Prepare operations for reading error on option. */ static void prvPrepareErrorOption() { uint8_t ucVal; uint16_t usVal; prvSetBitOperationStub(); /* Provide the message type and transaction ID for DHCPv6. */ ucVal = DHCPv6_message_Type_Advertise; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "TypeAdvertise" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestDHCPv6TransactionID, 3, "TransactionID" ); /* Option Client ID */ usVal = DHCPv6_Option_Client_Identifier; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientID" ); usVal = 14U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionClientIDLength" ); vAddBitOperation( eTestDHCPv6BitOperationSetError, 0, 0, "SetError" ); } /** * @brief Prepare content with status code but the option length is less than minimal requirement. */ static void prvPrepareAdvertiseStatusCodeLengthTooSmall() { uint8_t ucVal; uint16_t usVal; uint32_t ulVal; xBitConfig_init_Stub( xStubxBitConfig_init ); pucBitConfig_peek_last_index_uc_Stub( xStubpucBitConfig_peek_last_index_uc ); ucBitConfig_read_8_Stub( xStubucBitConfig_read_8 ); xBitConfig_read_uc_Stub( xStubxBitConfig_read_uc ); usBitConfig_read_16_Stub( xStubusBitConfig_read_16 ); ulBitConfig_read_32_Stub( xStubulBitConfig_read_32 ); vBitConfig_release_Ignore(); /* Provide the message type and transaction ID for DHCPv6. */ ucVal = DHCPv6_message_Type_Advertise; vAddBitOperation( eTestDHCPv6BitOperationRead8, &ucVal, 1, "TypeAdvertise" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucTestDHCPv6TransactionID, 3, "TransactionID" ); /* Option Status Code */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatus" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusLength" ); } /** * @brief Prepare content with status code but the option length is larger than packet size. */ static void prvPrepareAdvertiseStatusCodeLengthTooBig() { uint16_t usVal; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); /* Option Status Code */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatus" ); usVal = 0xFFFF; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusLength" ); } /** * @brief Prepare status code with long message. */ static void prvPrepareAdvertiseStatusCodeLongMessage() { uint16_t usVal; /* For now, local buffer size is 50. Declare a message with larger size. */ const uint8_t ucStatusCodeLongMessage[] = "012345678901234567890123456789012345678901234567890123456789"; prvSetBitOperationStub(); prvAddMsgHeader( pdFALSE, DHCPv6_message_Type_Advertise ); /* Option Status Code */ usVal = DHCPv6_Option_Status_Code; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatus" ); usVal = sizeof( ucStatusCodeLongMessage ) + 2; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusLength" ); usVal = 1U; vAddBitOperation( eTestDHCPv6BitOperationRead16, &usVal, 2, "OptionStatusValue" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, ucStatusCodeLongMessage, 49, "OptionStatusMessage" ); vAddBitOperation( eTestDHCPv6BitOperationReadCustom, &( ucStatusCodeLongMessage[ 49 ] ), sizeof( ucStatusCodeLongMessage ) - 49, "OptionStatusMessage2" ); } /** * @brief Check if eGetDHCPv6State can return DHCP state correctly. */ void test_eGetDHCPv6State_HappyPath() { NetworkEndPoint_t xEndPoint; eDHCPState_t eState = eInitialWait, eStateMax = eNotUsingLeasedAddress; eDHCPState_t eReturnState; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); for( eState = eInitialWait; eState <= eNotUsingLeasedAddress; eState++ ) { xEndPoint.xDHCPData.eDHCPState = eState; eReturnState = eGetDHCPv6State( &xEndPoint ); TEST_ASSERT_EQUAL( eState, eReturnState ); } } /** * @brief Check if eGetDHCPv6State trigger assertion when input is NULL. */ void test_eGetDHCPv6State_NullInput() { catch_assert( eGetDHCPv6State( NULL ) ); } /** * @brief Check if vDHCPv6Process trigger assertion when input is NULL. */ void test_vDHCPv6Process_NullInput() { catch_assert( vDHCPv6Process( pdTRUE, NULL ) ); catch_assert( vDHCPv6Process( pdFALSE, NULL ) ); } /** * @brief Check if vDHCPv6Process can reset successfully from eInitialWait. */ void test_vDHCPv6Process_ResetFromInit() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); xEndPoint.xDHCPData.eDHCPState = eInitialWait; xEndPoint.xDHCPData.eExpectedState = eInitialWait; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket, pdTRUE ); prvSetCheckerAndReturn_FreeRTOS_setsockopt( &xLocalDHCPv6Socket, sizeof( TickType_t ) ); FreeRTOS_setsockopt_Stub( xStubFreeRTOS_setsockopt ); prvSetCheckerAndReturn_vSocketBind( &xLocalDHCPv6Socket ); vSocketBind_Stub( xStubvSocketBind ); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdTRUE, &xEndPoint ); /* The endpoint sends the DHCPv6 Solicitation message to find the DHCPv6 server. * Then change the state to eWaitingSendFirstDiscover. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint.xDHCPData.eDHCPState ); /* We should set 2 socket options (FREERTOS_SO_RCVTIMEO and FREERTOS_SO_SNDTIMEO). */ TEST_ASSERT_EQUAL( ( 1 << FREERTOS_SO_RCVTIMEO | 1 << FREERTOS_SO_SNDTIMEO ), xStubFreeRTOS_setsockopt_lOptionName_BitMap ); } /** * @brief Check if vDHCPv6Process can reset successfully from eLeasedAddress. */ void test_vDHCPv6Process_ResetFromLease() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; const IPv6_Address_t xIPAddress = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; DHCPMessage_IPv6_t xDHCPMessage; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); xEndPoint.xDHCPData.eDHCPState = eLeasedAddress; xEndPoint.xDHCPData.eExpectedState = eLeasedAddress; memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket, pdTRUE ); prvSetCheckerAndReturn_FreeRTOS_setsockopt( &xLocalDHCPv6Socket, sizeof( TickType_t ) ); FreeRTOS_setsockopt_Stub( xStubFreeRTOS_setsockopt ); prvSetCheckerAndReturn_vSocketBind( &xLocalDHCPv6Socket ); vSocketBind_Stub( xStubvSocketBind ); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdTRUE, &xEndPoint ); /* The endpoint sends the DHCPv6 Solicitation message to find the DHCPv6 server. * Then change the state to eWaitingSendFirstDiscover. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint.xDHCPData.eDHCPState ); /* We should set 2 socket options (FREERTOS_SO_RCVTIMEO and FREERTOS_SO_SNDTIMEO). */ TEST_ASSERT_EQUAL( ( 1 << FREERTOS_SO_RCVTIMEO | 1 << FREERTOS_SO_SNDTIMEO ), xStubFreeRTOS_setsockopt_lOptionName_BitMap ); } /** * @brief Check if vDHCPv6Process can reset successfully when state is different from expect state. */ void test_vDHCPv6Process_ResetDifferentState() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; const IPv6_Address_t xIPAddress = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; DHCPMessage_IPv6_t xDHCPMessage; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); xEndPoint.xDHCPData.eDHCPState = eInitialWait; xEndPoint.xDHCPData.eExpectedState = eLeasedAddress; memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket, pdTRUE ); prvSetCheckerAndReturn_FreeRTOS_setsockopt( &xLocalDHCPv6Socket, sizeof( TickType_t ) ); FreeRTOS_setsockopt_Stub( xStubFreeRTOS_setsockopt ); prvSetCheckerAndReturn_vSocketBind( &xLocalDHCPv6Socket ); vSocketBind_Stub( xStubvSocketBind ); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdTRUE, &xEndPoint ); /* The endpoint sends the DHCPv6 Solicitation message to find the DHCPv6 server. * Then change the state to eWaitingSendFirstDiscover. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint.xDHCPData.eDHCPState ); /* We should set 2 socket options (FREERTOS_SO_RCVTIMEO and FREERTOS_SO_SNDTIMEO). */ TEST_ASSERT_EQUAL( ( 1 << FREERTOS_SO_RCVTIMEO | 1 << FREERTOS_SO_SNDTIMEO ), xStubFreeRTOS_setsockopt_lOptionName_BitMap ); } /** * @brief Check if vDHCPv6Process can continue from eWaitingSendFirstDiscover successfully. */ void test_vDHCPv6Process_SolicitationHappyPath() { 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 ) ); 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.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); /* Prepare bit message for solicitation. */ prvPrepareSolicitation(); vDHCPv6Process( pdFALSE, &xEndPoint ); /* The endpoint sends the DHCPv6 Solicitation message to find the DHCPv6 server. * Then change the state to eWaitingOffer. */ TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( 0, xDHCPMessage.ulTimeStamp ); TEST_ASSERT_EQUAL( TEST_DHCPV6_TRANSACTION_ID, xEndPoint.xDHCPData.ulTransactionId ); } /** * @brief Check if vDHCPv6Process can stop when state is different from expect state. */ void test_vDHCPv6Process_SolicitationDifferentState() { 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 ) ); 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.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eLeasedAddress; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can continue from eWaitingOffer successfully. */ void test_vDHCPv6Process_AdvertiseHappyPath() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertise(); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); vDHCPv6Process( pdFALSE, &xEndPoint ); /* The endpoint receives the DHCPv6 Advertise message from DHCPv6 server. * Then change the state to eWaitingAcknowledge. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can ignore IA_TA option which is not supported. */ void test_vDHCPv6Process_AdvertiseIATA() { 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_IgnoreAndReturn( 93 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseIATA(); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); vDHCPv6Process( pdFALSE, &xEndPoint ); /* The endpoint receives the DHCPv6 Advertise message from DHCPv6 server. * Then change the state to eWaitingAcknowledge. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can continue from eWaitingAcknowledge successfully. */ void test_vDHCPv6Process_ReplyHappyPath() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReply(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6DEFAULT_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief The address of endpoint is timeout. Endpoint sends the DHCPv6 request to ask for renew. */ void test_vDHCPv6Process_DHCPLeaseTimeout() { 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 = eLeasedAddress; xEndPoint.xDHCPData.eExpectedState = eLeasedAddress; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xDHCPv6Socket = &xLocalDHCPv6Socket; /* Assume that DHCPv6 had got the advertise and sent request once. */ xEndPoint.xDHCPData.xDHCPTxTime = pdMS_TO_TICKS( 0 ); xEndPoint.xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 5000 ); memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); /* Because we assume DHCPv6 got advertise, so we should set the server information in DHCP message. */ xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.uxLength = 10U; /* 14 - 4 */ xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.usHardwareType = 1U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* The address of endpoint is leased. Endpoint sends the DHCPv6 request to ask for renew. * Then change the state to eWaitingAcknowledge. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief When the socket is failed on creation, we should use default setting as IP address. */ void test_vDHCPv6Process_GiveupWhenSocketNull() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); pxNetworkEndPoints = &xEndPoint; memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); memcpy( xEndPoint.ipv6_defaults.xIPAddress.ucBytes, &xDefaultIPAddress.ucBytes, sizeof( IPv6_Address_t ) ); memcpy( xEndPoint.ipv6_defaults.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); xEndPoint.ipv6_defaults.uxPrefixLength = 64; xEndPoint.bits.bIPv6 = pdTRUE; xEndPoint.bits.bWantDHCP = pdTRUE; xEndPoint.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = NULL; xEndPoint.pxDHCPMessage = &xDHCPMessage; vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* When giving up, the state is set to eNotUsingLeasedAddress. Then using default setting as IPv6 address. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief Check if vDHCPv6Process send another DHCPv6 reply when timeout triggered on waiting reply. * Then reset the state to initial when timeout period is out of bound. */ void test_vDHCPv6Process_WaitReplyTimeout() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; /* Assume that DHCPv6 had got the advertise and sent request once. */ xEndPoint.xDHCPData.xDHCPTxTime = pdMS_TO_TICKS( 0 ); xEndPoint.xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 5000 ); memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); /* Because we assume DHCPv6 got advertise, so we should set the server information in DHCP message. */ xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.uxLength = 10U; /* 14 - 4 */ xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.usHardwareType = 1U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); /* 1st timeout at 5001ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) ); /* Update tx time to 5001ms. And the tx period is updated to 10000ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) ); /* 2nd timeout at 5001 + 10001 ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) ); /* Update tx time to 5001ms + 10001 ms. And the tx period is updated to 20000ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) ); /* 3rd timeout at 5001 + 10001 + 20001 ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) + pdMS_TO_TICKS( 20001 ) ); /* Timeout triggered. Reset the DHCPv6 to initial state */ /* 1st timeout makes 1st request message resend. */ xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); /* 2nd timeout makes 2nd request message resend. */ xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpINITIAL_TIMER_PERIOD ); /* 1st process to trigger 1st timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); /* 2nd process to trigger 2nd timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); /* 3rd process to trigger final timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eInitialWait, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets with unknown message type. */ void test_vDHCPv6Process_prvDHCPv6Analyse_UnknownMsgType() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareUnknownMsgType(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets with wrong transaction ID. */ void test_vDHCPv6Process_prvDHCPv6Analyse_WrongTransactionID() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareWrongTransactionID(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets while error occurred on bit configuration. */ void test_vDHCPv6Process_prvDHCPv6Analyse_ReadTransactionIDError() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareErrorTransactionID(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets while error occurred on reading option. */ void test_vDHCPv6Process_prvDHCPv6Analyse_ReadOptionError() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareErrorOption(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets while advertise message without server ID. */ void test_vDHCPv6Process_prvDHCPv6Analyse_LackServerID() { 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_IgnoreAndReturn( 126 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseNoServerID(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets while failing on initialization of bit configuration. */ void test_vDHCPv6Process_prvDHCPv6Analyse_BitConfigInitError() { 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_IgnoreAndReturn( 126 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); xBitConfig_init_IgnoreAndReturn( pdFAIL ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets when any option's length is less than minimal requirement. */ void test_vDHCPv6Process_prvIsOptionLengthValid_OptionLessThanMinLength() { 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_IgnoreAndReturn( 500 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseStatusCodeLengthTooSmall(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packets when any option's length is larger than packet size. */ void test_vDHCPv6Process_prvIsOptionLengthValid_OptionLargerThanMaxLength() { 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_IgnoreAndReturn( 500 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseStatusCodeLengthTooBig(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can truncate the message in the local buffer. */ void test_vDHCPv6Process_prvDHCPv6_handleStatusCode_MessageTooLong() { 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_IgnoreAndReturn( 71 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseStatusCodeLongMessage(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Receive the message when global endpoint list is empty. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_EmptyEndpointList() { 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 ) ); 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertise(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if DHCPv6 can search endpoint correctly. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_MultipleEndpoints() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; /* 3 endpoints: * - IPv4 endpoint with DHCP disabled * - IPv4 endpoint with DHCP enabled * - IPv6 endpoint with DHCP disabled * - IPv6 endpoint with DHCP enabled with different transaction ID * - IPv6 endpoint with DHCP enabled with state eLeasedAddress */ NetworkEndPoint_t xMultipleEndPoint[ 5 ]; const uint32_t ulDifferentTransactionID = 0x111111; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xMultipleEndPoint[ 0 ], 0, sizeof( NetworkEndPoint_t ) ); memcpy( xMultipleEndPoint[ 0 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); xMultipleEndPoint[ 0 ].bits.bIPv6 = pdFALSE; xMultipleEndPoint[ 0 ].bits.bWantDHCP = pdFALSE; memset( &xMultipleEndPoint[ 1 ], 0, sizeof( NetworkEndPoint_t ) ); memcpy( xMultipleEndPoint[ 1 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); xMultipleEndPoint[ 1 ].bits.bIPv6 = pdFALSE; xMultipleEndPoint[ 1 ].bits.bWantDHCP = pdTRUE; memset( &xMultipleEndPoint[ 2 ], 0, sizeof( NetworkEndPoint_t ) ); memcpy( xMultipleEndPoint[ 2 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); xMultipleEndPoint[ 2 ].bits.bIPv6 = pdTRUE; xMultipleEndPoint[ 2 ].bits.bWantDHCP = pdFALSE; memset( &xMultipleEndPoint[ 3 ], 0, sizeof( NetworkEndPoint_t ) ); memcpy( xMultipleEndPoint[ 3 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); xMultipleEndPoint[ 3 ].bits.bIPv6 = pdTRUE; xMultipleEndPoint[ 3 ].bits.bWantDHCP = pdTRUE; xMultipleEndPoint[ 3 ].xDHCPData.eDHCPState = eWaitingOffer; xMultipleEndPoint[ 3 ].xDHCPData.eExpectedState = eWaitingOffer; xMultipleEndPoint[ 3 ].xDHCPData.ulTransactionId = ulDifferentTransactionID; memset( &xMultipleEndPoint[ 4 ], 0, sizeof( NetworkEndPoint_t ) ); memcpy( xMultipleEndPoint[ 4 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); xMultipleEndPoint[ 4 ].bits.bIPv6 = pdTRUE; xMultipleEndPoint[ 4 ].bits.bWantDHCP = pdTRUE; xMultipleEndPoint[ 4 ].xDHCPData.eDHCPState = eLeasedAddress; xMultipleEndPoint[ 4 ].xDHCPData.eExpectedState = eLeasedAddress; xMultipleEndPoint[ 4 ].xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; pxNetworkEndPoints = &xMultipleEndPoint[ 0 ]; xMultipleEndPoint[ 0 ].pxNext = &xMultipleEndPoint[ 1 ]; xMultipleEndPoint[ 1 ].pxNext = &xMultipleEndPoint[ 2 ]; xMultipleEndPoint[ 2 ].pxNext = &xMultipleEndPoint[ 3 ]; xMultipleEndPoint[ 3 ].pxNext = &xMultipleEndPoint[ 4 ]; xMultipleEndPoint[ 4 ].pxNext = &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; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 10U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertise(); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareRequest(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief The server DUID type in reply message is different from advertise. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerDUIDType() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 14U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDifferentServerDUIDType(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief The server ID length in reply message is different from advertise. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerLength() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 10U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 100 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDifferentServerLength(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief The server ID length in reply message is invalid. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerLength_HigherThanThreshold() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 150U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 100 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDifferentServerLength(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief The server DUID in reply message is different from advertise. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentServerDUID() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 10U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDifferentServerDUID(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief DHCPv6 agent receives the message for different endpoint. */ void test_vDHCPv6Process_xDHCPv6Process_PassReplyToEndPoint_DifferentEndpoint() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; NetworkEndPoint_t xDifferentEndPoint; DHCPMessage_IPv6_t xDifferentDHCPMessage; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xDifferentDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); pxNetworkEndPoints = &xEndPoint; memset( &xDifferentEndPoint, 0, sizeof( NetworkEndPoint_t ) ); xDifferentEndPoint.xDHCPData.eDHCPState = eWaitingAcknowledge; xDifferentEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xDifferentEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xDifferentEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xDifferentEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xDifferentEndPoint.pxDHCPMessage = &xDifferentDHCPMessage; 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; xDHCPMessage.xServerID.usDUIDType = 1U; xDHCPMessage.xServerID.uxLength = 10U; memcpy( xDHCPMessage.xServerID.pucID, ucTestDHCPv6OptionServerID, sizeof( ucTestDHCPv6OptionServerID ) ); FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReply(); /* These are happened on different endpoint */ vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6DEFAULT_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xDifferentEndPoint ); /* The reply is for endpoint. The state is changed to eLeasedAddress. */ TEST_ASSERT_EQUAL( eLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); /* No message for different endpoint. Keep in same state. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDifferentEndPoint.xDHCPData.eDHCPState ); } /** * @brief DHCPv6 reset but get failure when allocating memory by pvPortMalloc. */ void test_vDHCPv6Process_ResetAllocateFail() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; const IPv6_Address_t xIPAddress = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); xEndPoint.xDHCPData.eDHCPState = eLeasedAddress; memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.pxDHCPMessage = NULL; vAddStubsOperation( eTestStubsAllocateFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vDHCPv6Process( pdTRUE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); /* We should set 2 socket options (FREERTOS_SO_RCVTIMEO and FREERTOS_SO_SNDTIMEO). */ TEST_ASSERT_EQUAL( ( 1 << FREERTOS_SO_RCVTIMEO | 1 << FREERTOS_SO_SNDTIMEO ), xStubFreeRTOS_setsockopt_lOptionName_BitMap ); } /** * @brief FreeRTOS_recvfrom returns failure. */ void test_vDHCPv6Process_RecvFailure() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( -pdFREERTOS_ERRNO_ENOTCONN ); xTaskGetTickCount_IgnoreAndReturn( 0 ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief FreeRTOS_recvfrom returns pdFREERTOS_ERRNO_EAGAIN. */ void test_vDHCPv6Process_RecvEagain() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( -pdFREERTOS_ERRNO_EAGAIN ); xTaskGetTickCount_IgnoreAndReturn( 0 ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Got 1 DNS server info from reply message. */ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_WithDNS() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 122 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyWithDNS(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6DEFAULT_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief Got multiple DNS server info from reply message. */ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_ManyDNS() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 154 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyWithMultipleDNS(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6DEFAULT_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief Got reply message with short lease time. Should update lease time to minimum value. */ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_ShortLeaseTime() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.xDHCPData.ulLeaseTime = dhcpv6MINIMUM_LEASE_TIME - 1; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReply(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6MINIMUM_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief Got reply message with valid lease time. */ void test_vDHCPv6Process_vDHCPv6ProcessEndPoint_HandleReply_CustomLeaseTime() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.xDHCPData.ulLeaseTime = dhcpv6MINIMUM_LEASE_TIME + 1; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReply(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6MINIMUM_LEASE_TIME + 1 ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief xApplicationDHCPHook_Multi returns fail while receiving advertise. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleAdvertise_HookFailure() { 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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); prvPrepareAdvertise(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief xApplicationDHCPHook_Multi returns eDHCPUseDefaults while receiving advertise. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleAdvertise_HookDefault() { 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_defaults.xIPAddress.ucBytes, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.ipv6_defaults.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_IgnoreAndReturn( 144 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookUseDefault ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); prvPrepareAdvertise(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_defaults.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief Check if xDHCPv6ProcessEndPoint_HandleState triggers assertion when receiving NULL message pointer. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleState_NullMessage() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); pxNetworkEndPoints = &xEndPoint; memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); memcpy( xEndPoint.ipv6_defaults.xIPAddress.ucBytes, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.ipv6_defaults.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 = NULL; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); catch_assert( vDHCPv6Process( pdFALSE, &xEndPoint ) ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief DHCPv6 should skip sending solicitation when hook return fail. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleState_HookFailure() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; DHCPMessage_IPv6_t xDHCPMessage; 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_defaults.xIPAddress.ucBytes, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.ipv6_defaults.uxPrefixLength = 64; xEndPoint.bits.bIPv6 = pdTRUE; xEndPoint.bits.bWantDHCP = pdTRUE; xEndPoint.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eWaitingSendFirstDiscover; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief DHCPv6 should skip sending solicitation when hook return eDHCPUseDefaults. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleState_HookDefault() { NetworkEndPoint_t xEndPoint; struct xSOCKET xLocalDHCPv6Socket; DHCPMessage_IPv6_t xDHCPMessage; 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_defaults.xIPAddress.ucBytes, xDefaultIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); xEndPoint.ipv6_defaults.uxPrefixLength = 64; xEndPoint.bits.bIPv6 = pdTRUE; xEndPoint.bits.bWantDHCP = pdTRUE; xEndPoint.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eWaitingSendFirstDiscover; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookUseDefault ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process send another DHCPv6 solicitation when timeout triggered on waiting advertise. * Then reset the state to initial when timeout period is out of bound. */ void test_vDHCPv6Process_WaitAdvertiseTimeout() { 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; /* Assume that DHCPv6 has sent solicitation once. */ xEndPoint.xDHCPData.xDHCPTxTime = pdMS_TO_TICKS( 0 ); xEndPoint.xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 5000 ); memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); /* Because we assume DHCPv6 got advertise, so we should set the server information in DHCP message. */ xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); /* 1st timeout at 5001ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) ); /* Update tx time to 5001ms. And the tx period is updated to 10000ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) ); /* 2nd timeout at 5001 + 10001 ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) ); /* Update tx time to 5001ms + 10001 ms. And the tx period is updated to 20000ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) ); /* 3rd timeout at 5001 + 10001 + 20001 ms. */ xTaskGetTickCount_IgnoreAndReturn( pdMS_TO_TICKS( 5001 ) + pdMS_TO_TICKS( 10001 ) + pdMS_TO_TICKS( 20001 ) ); /* Timeout triggered. Reset the DHCPv6 to initial state */ /* 1st timeout makes 1st solicitation message resend. */ xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareSolicitation(); /* 2nd timeout makes 2nd solicitation message resend. */ xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); prvPrepareSolicitation(); /* Final timeout, giving up. */ vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint ); /* 1st process to trigger 1st timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); /* 2nd process to trigger 2nd timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); /* 3rd process to trigger final timeout. */ vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process disables the timer when the state is eNotUsingLeasedAddress. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleState_NotUsingLeasedAddress() { 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 ) ); xEndPoint.bits.bIPv6 = pdTRUE; xEndPoint.bits.bWantDHCP = pdTRUE; xEndPoint.xDHCPData.eDHCPState = eNotUsingLeasedAddress; xEndPoint.xDHCPData.eExpectedState = eNotUsingLeasedAddress; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; /* Because we assume DHCPv6 got advertise, so we should set the server information in DHCP message. */ xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint, pdFALSE ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process ignore everything in unknown state. */ void test_vDHCPv6Process_xDHCPv6ProcessEndPoint_HandleState_UnknownState() { 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 ) ); xEndPoint.bits.bIPv6 = pdTRUE; xEndPoint.bits.bWantDHCP = pdTRUE; xEndPoint.xDHCPData.eDHCPState = 0xFE; xEndPoint.xDHCPData.eExpectedState = 0xFE; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; /* Because we assume DHCPv6 got advertise, so we should set the server information in DHCP message. */ xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( 0xFE, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Endpoints should close the socket when last endpoint request to close the socket. */ void test_vDHCPv6Process_prvCloseDHCPv6Socket_MultipleEndpointsCloseSockets() { NetworkEndPoint_t xEndPoint[ 2 ]; DHCPMessage_IPv6_t xDHCPMessage[ 2 ]; struct xSOCKET xLocalDHCPv6Socket[ 2 ]; /* Initialize first endpoint */ memset( &xEndPoint[ 0 ], 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage[ 0 ], 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); memcpy( xEndPoint[ 0 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); memcpy( xEndPoint[ 0 ].ipv6_settings.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); xEndPoint[ 0 ].ipv6_settings.uxPrefixLength = 64; xEndPoint[ 0 ].bits.bIPv6 = pdTRUE; xEndPoint[ 0 ].bits.bWantDHCP = pdTRUE; xEndPoint[ 0 ].xDHCPData.eDHCPState = eWaitingOffer; xEndPoint[ 0 ].xDHCPData.eExpectedState = eWaitingOffer; xEndPoint[ 0 ].xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint[ 0 ].xDHCPData.xDHCPSocket = NULL; memcpy( xEndPoint[ 0 ].xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint[ 0 ].pxDHCPMessage = &xDHCPMessage[ 0 ]; pxNetworkEndPoints = &xEndPoint[ 0 ]; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket[ 0 ] ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket[ 0 ], pdTRUE ); prvSetCheckerAndReturn_FreeRTOS_setsockopt( &xLocalDHCPv6Socket[ 0 ], sizeof( TickType_t ) ); FreeRTOS_setsockopt_Stub( xStubFreeRTOS_setsockopt ); prvSetCheckerAndReturn_vSocketBind( &xLocalDHCPv6Socket[ 0 ] ); vSocketBind_Stub( xStubvSocketBind ); vDHCP_RATimerReload_Expect( &xEndPoint[ 0 ], dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdTRUE, &xEndPoint[ 0 ] ); TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint[ 0 ].xDHCPData.eDHCPState ); /* Initialize second endpoint */ memset( &xEndPoint[ 1 ], 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage[ 1 ], 0, sizeof( DHCPMessage_IPv6_t ) ); memcpy( xEndPoint[ 1 ].xMACAddress.ucBytes, ucDefaultMACAddress, sizeof( ucDefaultMACAddress ) ); memcpy( xEndPoint[ 1 ].ipv6_settings.xPrefix.ucBytes, &xDefaultNetPrefix.ucBytes, sizeof( IPv6_Address_t ) ); xEndPoint[ 1 ].ipv6_settings.uxPrefixLength = 64; xEndPoint[ 1 ].bits.bIPv6 = pdTRUE; xEndPoint[ 1 ].bits.bWantDHCP = pdTRUE; xEndPoint[ 1 ].xDHCPData.eDHCPState = eWaitingOffer; xEndPoint[ 1 ].xDHCPData.eExpectedState = eWaitingOffer; xEndPoint[ 1 ].xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; memcpy( xEndPoint[ 1 ].xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint[ 1 ].pxDHCPMessage = &xDHCPMessage[ 1 ]; xEndPoint[ 1 ].xDHCPData.xDHCPSocket = NULL; pxNetworkEndPoints->pxNext = &xEndPoint[ 1 ]; vDHCP_RATimerReload_Expect( &xEndPoint[ 1 ], dhcpINITIAL_TIMER_PERIOD ); vDHCPv6Process( pdTRUE, &xEndPoint[ 1 ] ); TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xEndPoint[ 1 ].xDHCPData.eDHCPState ); /* Process 1st endpoint again but got failure at DHCP hook callback. */ xEndPoint[ 0 ].xDHCPData.eExpectedState = eWaitingSendFirstDiscover; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint[ 0 ], pdFALSE ); vIPNetworkUpCalls_Expect( &xEndPoint[ 0 ] ); vDHCPv6Process( pdFALSE, &xEndPoint[ 0 ] ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint[ 0 ].xDHCPData.eDHCPState ); /* Process 2nd endpoint again but got failure at DHCP hook callback. Trigger socket close flow */ xEndPoint[ 1 ].xDHCPData.eExpectedState = eWaitingSendFirstDiscover; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); vAddStubsOperation( eTestStubsHookFail ); vIPSetDHCP_RATimerEnableState_Expect( &xEndPoint[ 1 ], pdFALSE ); vSocketClose_ExpectAndReturn( &xLocalDHCPv6Socket[ 0 ], NULL ); vIPNetworkUpCalls_Expect( &xEndPoint[ 1 ] ); vDHCPv6Process( pdFALSE, &xEndPoint[ 1 ] ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xEndPoint[ 1 ].xDHCPData.eDHCPState ); } /** * @brief When endpoint should do nothing when trying to close socket but no one created it. */ void test_prvCloseDHCPv6Socket_CloseSocketWithoutCreate() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; /* Initialize first endpoint */ memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); 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; xDHCPv6Socket = &xLocalDHCPv6Socket; pxNetworkEndPoints = &xEndPoint; prvCloseDHCPv6Socket( &xEndPoint ); } /** * @brief Endpoints should trigger assertion when FreeRTOS_socket return invalid socket handler. */ void test_vDHCPv6Process_prvCreateDHCPv6Socket_CreateSocketFail() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); 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 = NULL; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; pxNetworkEndPoints = &xEndPoint; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket, pdFALSE ); catch_assert( vDHCPv6Process( pdTRUE, &xEndPoint ) ); } /** * @brief Endpoints should trigger assertion when vSocketBind return fail. */ void test_vDHCPv6Process_prvCreateDHCPv6Socket_BindSocketFail() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); 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 = NULL; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; pxNetworkEndPoints = &xEndPoint; FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET6, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xLocalDHCPv6Socket ); xSocketValid_ExpectAndReturn( &xLocalDHCPv6Socket, pdTRUE ); prvSetCheckerAndReturn_FreeRTOS_setsockopt( &xLocalDHCPv6Socket, sizeof( TickType_t ) ); FreeRTOS_setsockopt_Stub( xStubFreeRTOS_setsockopt ); vSocketBind_IgnoreAndReturn( 1 ); catch_assert( vDHCPv6Process( pdTRUE, &xEndPoint ) ); } /** * @brief NULL endpoint pointer. */ void test_prvSendDHCPMessage_NullEndpoint() { catch_assert( prvSendDHCPMessage( NULL ) ); } /** * @brief Check if DHCPv6 skip sending solicitation when it fail to get random number. */ void test_vDHCPv6Process_prvSendDHCPMessage_RandomFail() { 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 ) ); 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.xDHCPData.eDHCPState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.eExpectedState = eWaitingSendFirstDiscover; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); xApplicationGetRandomNumber_IgnoreAndReturn( pdFAIL ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if DHCPv6 skip sending solicitation when its socket is NULL. */ void test_vDHCPv6Process_prvSendDHCPMessage_NullSocket() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); 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.xDHCPData.eDHCPState = eWaitingOffer; xEndPoint.xDHCPData.eExpectedState = eWaitingOffer; xEndPoint.xDHCPData.xDHCPSocket = NULL; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 1 ); xTaskGetTickCount_IgnoreAndReturn( 1 ); xApplicationGetRandomNumber_IgnoreAndReturn( pdPASS ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if DHCPv6 skip sending solicitation when it fail to init bit configuration. */ void test_vDHCPv6Process_prvSendDHCPMessage_BitConfigInitFail() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); 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.xDHCPData.eDHCPState = eWaitingOffer; xEndPoint.xDHCPData.eExpectedState = eWaitingOffer; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 1 ); xTaskGetTickCount_IgnoreAndReturn( 1 ); xApplicationGetRandomNumber_IgnoreAndReturn( pdPASS ); xBitConfig_init_IgnoreAndReturn( pdFALSE ); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if prvSendDHCPMessage stop sending when the state is unexpected. */ void test_prvSendDHCPMessage_UnexpectState() { NetworkEndPoint_t xEndPoint; DHCPMessage_IPv6_t xDHCPMessage; struct xSOCKET xLocalDHCPv6Socket; memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); memset( &xDHCPMessage, 0, sizeof( DHCPMessage_IPv6_t ) ); memset( &xLocalDHCPv6Socket, 0, sizeof( struct xSOCKET ) ); 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.xDHCPData.eDHCPState = 0xFF; xEndPoint.xDHCPData.eExpectedState = 0xFF; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; xApplicationGetRandomNumber_IgnoreAndReturn( pdPASS ); xBitConfig_init_IgnoreAndReturn( pdTRUE ); vBitConfig_release_Ignore(); xEndPoint.pxDHCPMessage = &xDHCPMessage; prvSendDHCPMessage( &xEndPoint ); } /** * @brief Check if vDHCPv6Process can drop packet with invalid length IA_NA. */ void test_vDHCPv6Process_ReplyInvalidLengthIANA() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyInvalidIA_NA(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet with invalid length IA_PD. */ void test_vDHCPv6Process_ReplyInvalidLengthIAPD() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 102 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyInvalidIA_PD(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when sub-option is invalid in IA_NA. */ void test_vDHCPv6Process_ReplyInvalidSubOptionIANA() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyInvalidIA_NASubOption(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of client ID is too small. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_ClientLengthTooSmall() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDTooSmall(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of client ID is too big. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_ClientLengthTooBig() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDTooBig(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of client ID is wrong. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_WrongClientID() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDLengthWrong(); vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDPeekFalse(); vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyClientIDContentWrong(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of server ID is too small. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_ServerLengthTooSmall() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 256 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyServerIDTooSmall(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of server ID is too big. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_ServerLengthTooBig() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyServerIDTooBig(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of DNS is invalid. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_InvalidDNSLength() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDNSLengthZero(); vDHCPv6Process( pdFALSE, &xEndPoint ); FreeRTOS_recvfrom_IgnoreAndReturn( 512 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyDNSLengthNotAllow(); vDHCPv6Process( pdFALSE, &xEndPoint ); TEST_ASSERT_EQUAL( eWaitingAcknowledge, xEndPoint.xDHCPData.eDHCPState ); } /** * @brief Check if vDHCPv6Process can drop packet when option length of DNS is invalid. */ void test_vDHCPv6Process_prvDHCPv6_handleOption_DomainSearchList() { 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 = eWaitingAcknowledge; xEndPoint.xDHCPData.eExpectedState = eWaitingAcknowledge; xEndPoint.xDHCPData.ulTransactionId = TEST_DHCPV6_TRANSACTION_ID; xEndPoint.xDHCPData.xDHCPSocket = &xLocalDHCPv6Socket; memcpy( xEndPoint.xDHCPData.ucClientDUID, ucTestDHCPv6OptionClientID, sizeof( ucTestDHCPv6OptionClientID ) ); xEndPoint.pxDHCPMessage = &xDHCPMessage; FreeRTOS_recvfrom_IgnoreAndReturn( 108 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareReplyWithDomainSearchList(); vDHCP_RATimerReload_Expect( &xEndPoint, dhcpv6DEFAULT_LEASE_TIME ); vIPNetworkUpCalls_Expect( &xEndPoint ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* Check if the IP address provided in reply is set to endpoint properly. */ TEST_ASSERT_EQUAL_MEMORY( xDefaultIPAddress.ucBytes, xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } /** * @brief To cover rare scenario in prvStateName */ void test_prvStateName_Coverage() { ( void ) prvStateName( eNotUsingLeasedAddress ); ( void ) prvStateName( eSendDHCPRequest ); } /** * @brief Check if prvDHCPv6_subOption detects the invalid length. */ void test_prvDHCPv6_subOption_UsedLengthLarger() { DHCPOptionSet_t xSet; BitConfig_t xMessage; uint32_t ulVal; memset( &xSet, 0, sizeof( DHCPOptionSet_t ) ); memset( &xMessage, 0, sizeof( BitConfig_t ) ); xSet.uxOptionLength = 10U; xSet.uxStart = 0U; xMessage.uxIndex = 0U; prvSetBitOperationStub(); vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "Dummy1" ); vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "Dummy2" ); vAddBitOperation( eTestDHCPv6BitOperationRead32, &ulVal, 4, "Dummy3" ); prvDHCPv6_subOption( DHCPv6_Option_NonTemporaryAddress, &xSet, NULL, &xMessage ); } /** * @brief Check if vDHCPv6Process can ignore the advertise when sub-option status code returns fail. */ void test_vDHCPv6Process_AdvertiseStatusFail() { 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_IgnoreAndReturn( 123 ); FreeRTOS_recvfrom_IgnoreAndReturn( 0 ); xTaskGetTickCount_IgnoreAndReturn( 0 ); prvPrepareAdvertiseSubStatusCodeFail(); xApplicationGetRandomNumber_Stub( xStubxApplicationGetRandomNumber ); FreeRTOS_inet_pton6_IgnoreAndReturn( pdTRUE ); FreeRTOS_sendto_IgnoreAndReturn( 0 ); vDHCPv6Process( pdFALSE, &xEndPoint ); /* The endpoint receives the DHCPv6 Advertise message from DHCPv6 server. * Then change the state to eWaitingAcknowledge. */ TEST_ASSERT_EQUAL( eWaitingOffer, xEndPoint.xDHCPData.eDHCPState ); }