1 /*
2  * FreeRTOS+TCP <DEVELOPMENT BRANCH>
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * http://aws.amazon.com/freertos
25  * http://www.FreeRTOS.org
26  */
27 
28 
29 /* Include Unity header */
30 #include "unity.h"
31 
32 /* Include standard libraries */
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdint.h>
36 
37 #include "mock_task.h"
38 #include "mock_list.h"
39 
40 /* This must come after list.h is included (in this case, indirectly
41  * by mock_list.h). */
42 #include "mock_queue.h"
43 #include "mock_event_groups.h"
44 
45 #include "FreeRTOSIPConfig.h"
46 
47 #include "FreeRTOS_Routing.h"
48 
49 #include "catch_assert.h"
50 
51 /* ===========================  EXTERN VARIABLES  =========================== */
52 
53 /* Default IPv4 address is 192.168.123.223, which is 0xDF7BA8C0. */
54 #define IPV4_DEFAULT_ADDRESS       ( 0xDF7BA8C0 )
55 /* Default IPv4 netmask is 255.255.255.0, which is 0x00FFFFFF. */
56 #define IPV4_DEFAULT_NETMASK       ( 0x00FFFFFF )
57 /* Default IPv4 netmask is 192.168.123.254, which is 0xFE7BA8C0. */
58 #define IPV4_DEFAULT_GATEWAY       ( 0xFE7BA8C0 )
59 /* Default IPv4 netmask is 192.168.123.1, which is 0x017BA8C0. */
60 #define IPV4_DEFAULT_DNS_SERVER    ( 0x017BA8C0 )
61 
62 const uint8_t ucDefaultMACAddress_IPv4[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33 };
63 
64 /* Default IPv6 address is set to 2001::1 */
65 const IPv6_Address_t xDefaultIPAddress_IPv6 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
66 const uint8_t ucDefaultMACAddress_IPv6[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x11, 0x22, 0x33, 0xab, 0xcd, 0xef };
67 
68 /* ============================  Unity Fixtures  ============================ */
69 
70 /*! called before each test case */
setUp(void)71 void setUp( void )
72 {
73     pxNetworkEndPoints = NULL;
74     pxNetworkInterfaces = NULL;
75 }
76 
77 /* ==============================  Test Cases  ============================== */
78 
79 /**
80  * @brief FreeRTOS_MatchingEndpoint returns the endpoint matched for custom frame type.
81  *
82  * pxNetworkInterfaces is a global variable using in FreeRTOS_Routing as link list head of all interfaces.
83  * pxNetworkEndPoints is a global variable using in FreeRTOS_Routing as link list head of all endpoints.
84  *
85  * Test step:
86  *  - Create 1 interface and 1 endpoint.
87  *  - Put interface & endpoint into the list.
88  *  - Prepare an custom packet with:
89  *     - IP address 192.168.123.223.
90  *     - MAC address ab:cd:ef:11:22:33.
91  *     - Frame type in ethernet header 0xFF.
92  *  - Call FreeRTOS_MatchingEndpoint and check if returned endpoint is same.
93  */
test_FreeRTOS_MatchingEndpoint_MatchCustomFrameType()94 void test_FreeRTOS_MatchingEndpoint_MatchCustomFrameType()
95 {
96     NetworkInterface_t xNetworkInterface;
97     NetworkEndPoint_t xEndPoint;
98     NetworkEndPoint_t * pxEndPoint = NULL;
99     uint8_t * pcNetworkBuffer[ sizeof( TCPPacket_t ) + 4 ] __attribute__( ( aligned( 32 ) ) );
100     ProtocolPacket_t * pxProtocolPacket = ( ProtocolPacket_t * ) ( ( uintptr_t ) ( pcNetworkBuffer ) + 2U );
101 
102     /* Initialize network interface. */
103     memset( &xNetworkInterface, 0, sizeof( NetworkInterface_t ) );
104     pxNetworkInterfaces = &xNetworkInterface;
105 
106     /* Initialize endpoint. */
107     memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) );
108     xEndPoint.ipv4_settings.ulIPAddress = IPV4_DEFAULT_ADDRESS;
109     memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress_IPv4, sizeof( ucDefaultMACAddress_IPv4 ) );
110     xEndPoint.pxNetworkInterface = &xNetworkInterface;
111     pxNetworkEndPoints = &xEndPoint;
112 
113     /* Initialize network buffer. */
114     memset( pcNetworkBuffer, 0, sizeof( pcNetworkBuffer ) );
115     /* Ethernet part. */
116     memcpy( pxProtocolPacket->xTCPPacket.xEthernetHeader.xDestinationAddress.ucBytes, ucDefaultMACAddress_IPv4, ipMAC_ADDRESS_LENGTH_BYTES );
117     memcpy( pxProtocolPacket->xTCPPacket.xEthernetHeader.xSourceAddress.ucBytes, ucDefaultMACAddress_IPv4, ipMAC_ADDRESS_LENGTH_BYTES );
118     pxProtocolPacket->xTCPPacket.xEthernetHeader.usFrameType = 0xFF;
119     /* IP part. */
120     pxProtocolPacket->xTCPPacket.xIPHeader.ulSourceIPAddress = IPV4_DEFAULT_ADDRESS;
121     pxProtocolPacket->xTCPPacket.xIPHeader.ulDestinationIPAddress = IPV4_DEFAULT_ADDRESS;
122 
123     pxEndPoint = FreeRTOS_MatchingEndpoint( &xNetworkInterface, ( const uint8_t * ) pxProtocolPacket );
124     TEST_ASSERT_EQUAL( &xEndPoint, pxEndPoint );
125 }
126 
127 /**
128  * @brief FreeRTOS_MatchingEndpoint returns NULL when receiving IPv6 packet but no IPv6 endpoint in the list.
129  *
130  * pxNetworkInterfaces is a global variable using in FreeRTOS_Routing as link list head of all interfaces.
131  * pxNetworkEndPoints is a global variable using in FreeRTOS_Routing as link list head of all endpoints.
132  *
133  * Test step:
134  *  - Create 1 interface and 1 endpoint.
135  *  - Put interface & endpoint into the list.
136  *     - Assign 192.168.123.223 (IPV4_DEFAULT_ADDRESS) to the endpoint.
137  *     - Assign ab:cd:ef:11:22:33 (ucDefaultMACAddress_IPv4) to the endpoint.
138  *     - Assign 0xFF as frame type to the endpoint.
139  *     - Attach endpoint to interface.
140  *  - Call FreeRTOS_MatchingEndpoint and check if returned endpoint is NULL.
141  */
test_FreeRTOS_MatchingEndpoint_IPv6Disabled()142 void test_FreeRTOS_MatchingEndpoint_IPv6Disabled()
143 {
144     NetworkInterface_t xNetworkInterface;
145     NetworkEndPoint_t xEndPoint;
146     NetworkEndPoint_t * pxEndPoint = NULL;
147     uint8_t * pcNetworkBuffer[ sizeof( TCPPacket_IPv6_t ) + 4 ] __attribute__( ( aligned( 32 ) ) );
148     TCPPacket_IPv6_t * pxTCPPacket = ( TCPPacket_IPv6_t * ) ( ( uintptr_t ) ( pcNetworkBuffer ) + 2U );
149 
150     /* Initialize network interface. */
151     memset( &xNetworkInterface, 0, sizeof( NetworkInterface_t ) );
152     pxNetworkInterfaces = &xNetworkInterface;
153 
154     /* Initialize endpoint. */
155     memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) );
156     xEndPoint.ipv4_settings.ulIPAddress = IPV4_DEFAULT_ADDRESS;
157     memcpy( xEndPoint.xMACAddress.ucBytes, ucDefaultMACAddress_IPv4, sizeof( ucDefaultMACAddress_IPv4 ) );
158     xEndPoint.pxNetworkInterface = &xNetworkInterface;
159     pxNetworkEndPoints = &xEndPoint;
160 
161     /* Initialize network buffer. */
162     memset( pcNetworkBuffer, 0, sizeof( pcNetworkBuffer ) );
163     /* Ethernet part. */
164     memcpy( pxTCPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ucDefaultMACAddress_IPv6, ipMAC_ADDRESS_LENGTH_BYTES );
165     memcpy( pxTCPPacket->xEthernetHeader.xSourceAddress.ucBytes, ucDefaultMACAddress_IPv6, ipMAC_ADDRESS_LENGTH_BYTES );
166     pxTCPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE;
167     /* IP part. */
168     memcpy( pxTCPPacket->xIPHeader.xSourceAddress.ucBytes, xDefaultIPAddress_IPv6.ucBytes, ipSIZE_OF_IPv4_ADDRESS );
169     memcpy( pxTCPPacket->xIPHeader.xDestinationAddress.ucBytes, xDefaultIPAddress_IPv6.ucBytes, ipSIZE_OF_IPv4_ADDRESS );
170 
171     pxEndPoint = FreeRTOS_MatchingEndpoint( &xNetworkInterface, ( const uint8_t * ) pxTCPPacket );
172     TEST_ASSERT_EQUAL( NULL, pxEndPoint );
173 }
174 
175 /**
176  * @brief pcEndpointName can't get IPv6 address in string from endpoint due to IPv6 is disabled.
177  *
178  * pxNetworkInterfaces is a global variable using in FreeRTOS_Routing as link list head of all interfaces.
179  * pxNetworkEndPoints is a global variable using in FreeRTOS_Routing as link list head of all endpoints.
180  *
181  * Test step:
182  *  - Create 1 endpoint.
183  *     - Set the IP address to 2001::1 (xDefaultIPAddress_IPv6).
184  *  - Call pcEndpointName with enough buffer size.
185  *  - Check if return buffer string is NULL.
186  */
test_pcEndpointName_IPv6HappyPath()187 void test_pcEndpointName_IPv6HappyPath()
188 {
189     NetworkEndPoint_t xEndPoint;
190     FreeRTOS_Socket_t xSocket;
191     const char cIPString[] = "2001::1";
192     int lNameSize = sizeof( cIPString ) + 1;
193     char cName[ lNameSize ];
194     const char * pcName;
195 
196     /* Initialize network endpoint and add it to the list. */
197     memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) );
198     xEndPoint.bits.bIPv6 = pdTRUE;
199 
200     memset( &cName, 0, sizeof( cName ) );
201 
202     pcName = pcEndpointName( &xEndPoint, cName, lNameSize );
203     TEST_ASSERT_EQUAL_STRING( "NULL", pcName );
204 }
205 
206 /**
207  * @brief FreeRTOS_FindGateWay should be able to find the endpoint with valid IPv4 gateway address.
208  *
209  * pxNetworkInterfaces is a global variable using in FreeRTOS_Routing as link list head of all interfaces.
210  * pxNetworkEndPoints is a global variable using in FreeRTOS_Routing as link list head of all endpoints.
211  *
212  * Test step:
213  *  - Create 1 IPv4 endpoint and add it to the list.
214  *     - Set the gateway address to 192.168.123.254 (IPV4_DEFAULT_GATEWAY).
215  *  - Call FreeRTOS_FindGateWay with ipTYPE_IPv4.
216  *  - Check if returned endpoint is same.
217  */
test_FreeRTOS_FindGateWay_IPv4HappyPath(void)218 void test_FreeRTOS_FindGateWay_IPv4HappyPath( void )
219 {
220     NetworkEndPoint_t xEndPoint;
221     NetworkEndPoint_t * pxEndPoint = NULL;
222 
223     /* Initialize network endpoint and add it to the list. */
224     memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) );
225     xEndPoint.ipv4_settings.ulGatewayAddress = IPV4_DEFAULT_GATEWAY;
226     pxNetworkEndPoints = &xEndPoint;
227 
228     pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv4 );
229     TEST_ASSERT_EQUAL( &xEndPoint, pxEndPoint );
230 }
231 
232 /**
233  * @brief FreeRTOS_FindGateWay should be able to return NULL if no valid IPv4 gateway address.
234  *
235  * pxNetworkInterfaces is a global variable using in FreeRTOS_Routing as link list head of all interfaces.
236  * pxNetworkEndPoints is a global variable using in FreeRTOS_Routing as link list head of all endpoints.
237  *
238  * Test step:
239  *  - Create 1 IPv4 endpoint and add it to the list.
240  *     - Set the gateway address to 0 (invalid address).
241  *  - Call FreeRTOS_FindGateWay with ipTYPE_IPv4.
242  *  - Check if returned endpoint is NULL.
243  */
test_FreeRTOS_FindGateWay_IPv4NotFound(void)244 void test_FreeRTOS_FindGateWay_IPv4NotFound( void )
245 {
246     NetworkEndPoint_t xEndPoint;
247     NetworkEndPoint_t * pxEndPoint = NULL;
248 
249     /* Initialize network endpoint and add it to the list. */
250     memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) );
251     pxNetworkEndPoints = &xEndPoint;
252 
253     pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv4 );
254     TEST_ASSERT_EQUAL( NULL, pxEndPoint );
255 }
256