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_Sockets_DiffConfig2_list_macros.h"
43 
44 #include "mock_FreeRTOS_IP_Private.h"
45 #include "mock_NetworkBufferManagement.h"
46 
47 #include "FreeRTOS_Sockets.h"
48 
49 #include "catch_assert.h"
50 
51 #include "FreeRTOSIPConfig.h"
52 
53 /* ============================ EXTERN VARIABLES ============================ */
54 
55 /* 2001::1 */
56 static IPv6_Address_t xIPv6Address = { { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } };
57 
58 /* ============================== Test Cases ============================== */
59 
60 /**
61  * @brief Binding already bound socket.
62  * And the family of destination address is set as invalid value.
63  */
test_FreeRTOS_bind_SocketIsAlreadyBound_UseTempDestinationAddress(void)64 void test_FreeRTOS_bind_SocketIsAlreadyBound_UseTempDestinationAddress( void )
65 {
66     BaseType_t xReturn;
67     FreeRTOS_Socket_t xSocket;
68     struct freertos_sockaddr xAddress;
69     socklen_t xAddressLength;
70 
71     memset( &xAddress, 0, sizeof( xAddress ) );
72     xAddress.sin_family = FREERTOS_AF_INET + 1;
73 
74     xIsCallingFromIPTask_ExpectAndReturn( pdFALSE );
75 
76     listLIST_ITEM_CONTAINER_ExpectAndReturn( &( xSocket.xBoundSocketListItem ), ( struct xLIST * ) ( uintptr_t ) 0x11223344 );
77 
78     xReturn = FreeRTOS_bind( &xSocket, &xAddress, xAddressLength );
79 
80     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, xReturn );
81 }
82 
83 /**
84  * @brief Binding already bound socket.
85  * And the family of destination address is set as FREERTOS_AF_INET6.
86  */
test_FreeRTOS_bind_SocketIsAlreadyBound_IPv6DestinationAddress(void)87 void test_FreeRTOS_bind_SocketIsAlreadyBound_IPv6DestinationAddress( void )
88 {
89     BaseType_t xReturn;
90     FreeRTOS_Socket_t xSocket;
91     struct freertos_sockaddr xAddress;
92     socklen_t xAddressLength;
93 
94     memset( &xAddress, 0, sizeof( xAddress ) );
95     xAddress.sin_family = FREERTOS_AF_INET6;
96 
97     xIsCallingFromIPTask_ExpectAndReturn( pdFALSE );
98 
99     listLIST_ITEM_CONTAINER_ExpectAndReturn( &( xSocket.xBoundSocketListItem ), ( struct xLIST * ) ( uintptr_t ) 0x11223344 );
100 
101     xReturn = FreeRTOS_bind( &xSocket, &xAddress, xAddressLength );
102 
103     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, xReturn );
104 }
105 
106 /**
107  * @brief Binding already bound socket.
108  * And the family of destination address is set as FREERTOS_AF_INET.
109  */
test_FreeRTOS_bind_SocketIsAlreadyBound_IPv4DestinationAddress(void)110 void test_FreeRTOS_bind_SocketIsAlreadyBound_IPv4DestinationAddress( void )
111 {
112     BaseType_t xReturn;
113     FreeRTOS_Socket_t xSocket;
114     struct freertos_sockaddr xAddress;
115     socklen_t xAddressLength;
116 
117     memset( &xAddress, 0, sizeof( xAddress ) );
118     xAddress.sin_family = FREERTOS_AF_INET;
119 
120     xIsCallingFromIPTask_ExpectAndReturn( pdFALSE );
121 
122     listLIST_ITEM_CONTAINER_ExpectAndReturn( &( xSocket.xBoundSocketListItem ), ( struct xLIST * ) ( uintptr_t ) 0x11223344 );
123 
124     xReturn = FreeRTOS_bind( &xSocket, &xAddress, xAddressLength );
125 
126     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, xReturn );
127 }
128 
129 /**
130  * @brief Binding already bound socket.
131  * And the destination address is NULL.
132  */
test_FreeRTOS_bind_SocketIsAlreadyBound_NullDestinationAddress(void)133 void test_FreeRTOS_bind_SocketIsAlreadyBound_NullDestinationAddress( void )
134 {
135     BaseType_t xReturn;
136     FreeRTOS_Socket_t xSocket;
137     socklen_t xAddressLength;
138 
139     xIsCallingFromIPTask_ExpectAndReturn( pdFALSE );
140 
141     listLIST_ITEM_CONTAINER_ExpectAndReturn( &( xSocket.xBoundSocketListItem ), ( struct xLIST * ) ( uintptr_t ) 0x11223344 );
142 
143     xReturn = FreeRTOS_bind( &xSocket, NULL, xAddressLength );
144 
145     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, xReturn );
146 }
147 
148 /**
149  * @brief All fields are NULL in the socket.
150  */
test_FreeRTOS_connect_SocketValuesNULL_UseTempDestinationAddress(void)151 void test_FreeRTOS_connect_SocketValuesNULL_UseTempDestinationAddress( void )
152 {
153     BaseType_t xResult;
154     FreeRTOS_Socket_t xSocket;
155     struct freertos_sockaddr xAddress;
156     socklen_t xAddressLength;
157 
158     memset( &xAddress, 0, sizeof( xAddress ) );
159     xAddress.sin_family = FREERTOS_AF_INET6 + 1;
160 
161     memset( &xSocket, 0, sizeof( xSocket ) );
162 
163     xResult = FreeRTOS_connect( &xSocket, &xAddress, xAddressLength );
164 
165     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EBADF, xResult );
166 }
167 
168 /**
169  * @brief All fields are NULL in the socket.
170  * And the family of destination address is set as FREERTOS_AF_INET6.
171  */
test_FreeRTOS_connect_SocketValuesNULL_IPv6DestinationAddress(void)172 void test_FreeRTOS_connect_SocketValuesNULL_IPv6DestinationAddress( void )
173 {
174     BaseType_t xResult;
175     FreeRTOS_Socket_t xSocket;
176     struct freertos_sockaddr xAddress;
177     socklen_t xAddressLength;
178 
179     memset( &xAddress, 0, sizeof( xAddress ) );
180     xAddress.sin_family = FREERTOS_AF_INET6;
181 
182     memset( &xSocket, 0, sizeof( xSocket ) );
183 
184     xResult = FreeRTOS_connect( &xSocket, &xAddress, xAddressLength );
185 
186     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EBADF, xResult );
187 }
188 
189 /**
190  * @brief All fields are NULL in the socket.
191  * And the family of destination address is set as FREERTOS_AF_INET.
192  */
test_FreeRTOS_connect_SocketValuesNULL_IPv4DestinationAddress(void)193 void test_FreeRTOS_connect_SocketValuesNULL_IPv4DestinationAddress( void )
194 {
195     BaseType_t xResult;
196     FreeRTOS_Socket_t xSocket;
197     struct freertos_sockaddr xAddress;
198     socklen_t xAddressLength;
199 
200     memset( &xAddress, 0, sizeof( xAddress ) );
201     xAddress.sin_family = FREERTOS_AF_INET;
202 
203     memset( &xSocket, 0, sizeof( xSocket ) );
204 
205     xResult = FreeRTOS_connect( &xSocket, &xAddress, xAddressLength );
206 
207     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EBADF, xResult );
208 }
209 
210 /**
211  * @brief All fields are NULL in the socket.
212  * And the destination address is NULL.
213  */
test_FreeRTOS_connect_SocketValuesNULL_NullDestinationAddress(void)214 void test_FreeRTOS_connect_SocketValuesNULL_NullDestinationAddress( void )
215 {
216     BaseType_t xResult;
217     FreeRTOS_Socket_t xSocket;
218     socklen_t xAddressLength;
219 
220     memset( &xSocket, 0, sizeof( xSocket ) );
221 
222     xResult = FreeRTOS_connect( &xSocket, NULL, xAddressLength );
223 
224     TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, xResult );
225 }
226 
227 /**
228  * @brief Get UDPv6 packets property string.
229  * But IPv6 is disabled.
230  */
test_prvSocketProps_UDPv6()231 void test_prvSocketProps_UDPv6()
232 {
233     FreeRTOS_Socket_t xSocket;
234     IPv6_Address_t * pxIPv6SrcAddress = &xIPv6Address; /* 2001::1 */
235     uint16_t usSrcPort = 1024U;
236     const char * pcReturn;
237 
238     memset( &xSocket, 0, sizeof( xSocket ) );
239     xSocket.ucProtocol = FREERTOS_IPPROTO_UDP;
240     xSocket.bits.bIsIPv6 = pdTRUE;
241     memcpy( xSocket.xLocalAddress.xIP_IPv6.ucBytes, pxIPv6SrcAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
242     xSocket.usLocalPort = usSrcPort;
243 
244     pcReturn = prvSocketProps( &xSocket );
245 }
246 
247 /**
248  * @brief Get TCPv6 packets property string.
249  * But IPv6 is disabled.
250  */
test_prvSocketProps_TCPv6()251 void test_prvSocketProps_TCPv6()
252 {
253     FreeRTOS_Socket_t xSocket;
254     IPv6_Address_t * pxIPv6SrcAddress = &xIPv6Address;                                                                                          /* 2001::1 */
255     IPv6_Address_t xIPv6RemoteAddress = { { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } }; /* 2001::2 */
256     uint16_t usSrcPort = 1024U;
257     uint16_t usRemotePort = 2048U;
258     const char * pcReturn;
259 
260     memset( &xSocket, 0, sizeof( xSocket ) );
261     xSocket.ucProtocol = FREERTOS_IPPROTO_TCP;
262     xSocket.bits.bIsIPv6 = pdTRUE;
263     memcpy( xSocket.xLocalAddress.xIP_IPv6.ucBytes, pxIPv6SrcAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
264     xSocket.usLocalPort = usSrcPort;
265     memcpy( xSocket.u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, xIPv6RemoteAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
266     xSocket.u.xTCP.usRemotePort = usRemotePort;
267 
268     pcReturn = prvSocketProps( &xSocket );
269 }
270 
271 /**
272  * @brief Get local address from an IPv6 socket.
273  * But IPv6 is disabled.
274  */
test_FreeRTOS_GetLocalAddress_IPv6(void)275 void test_FreeRTOS_GetLocalAddress_IPv6( void )
276 {
277     size_t uxReturn;
278     FreeRTOS_Socket_t xSocket;
279     struct freertos_sockaddr xAddress;
280     IPv6_Address_t xIPAddress = { { 0x20 } };
281 
282     memset( &xSocket, 0, sizeof( xSocket ) );
283     memset( &xAddress, 0, sizeof( xAddress ) );
284 
285     xSocket.bits.bIsIPv6 = pdTRUE;
286     xSocket.usLocalPort = 0xAB12;
287     memcpy( xSocket.xLocalAddress.xIP_IPv6.ucBytes, xIPv6Address.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
288 
289     uxReturn = FreeRTOS_GetLocalAddress( &xSocket, &xAddress );
290 
291     TEST_ASSERT_EQUAL( 0, xAddress.sin_family );
292 }
293 
294 /**
295  * @brief IPv6 happy path.
296  * But IPv6 is disabled.
297  */
test_FreeRTOS_GetRemoteAddress_IPv6HappyPath(void)298 void test_FreeRTOS_GetRemoteAddress_IPv6HappyPath( void )
299 {
300     BaseType_t xReturn;
301     FreeRTOS_Socket_t xSocket;
302     struct freertos_sockaddr xAddress;
303 
304     memset( &xSocket, 0, sizeof( xSocket ) );
305     memset( &xAddress, 0, sizeof( xAddress ) );
306 
307     xSocket.bits.bIsIPv6 = pdTRUE_UNSIGNED;
308     xSocket.ucProtocol = FREERTOS_IPPROTO_TCP;
309     memcpy( xSocket.u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, xIPv6Address.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
310     xSocket.u.xTCP.usRemotePort = 0x1234;
311 
312     xReturn = FreeRTOS_GetRemoteAddress( &xSocket, &xAddress );
313 
314     TEST_ASSERT_EQUAL( sizeof( xAddress ), xReturn );
315 }
316 
317 /**
318  * @brief Query socket type of IPv6 socket.
319  * But IPv6 is disabled, it always return IPv4.
320  */
test_FreeRTOS_GetIPType_IPv6HappyPath(void)321 void test_FreeRTOS_GetIPType_IPv6HappyPath( void )
322 {
323     BaseType_t xReturn;
324     FreeRTOS_Socket_t xSocket;
325 
326     memset( &xSocket, 0, sizeof( xSocket ) );
327 
328     xSocket.bits.bIsIPv6 = pdTRUE_UNSIGNED;
329 
330     xReturn = FreeRTOS_GetIPType( &xSocket );
331 
332     TEST_ASSERT_EQUAL( ipTYPE_IPv4, xReturn );
333 }
334 
335 /**
336  * @brief This function just prints out some data.
337  * But IPv6 is disabled.
338  */
test_vTCPNetStat_IPv6Socket(void)339 void test_vTCPNetStat_IPv6Socket( void )
340 {
341     ListItem_t xLocalTCPItem, xLocalUDPItem, xIterator;
342     FreeRTOS_Socket_t xSocket;
343 
344     memset( &xSocket, 0, sizeof( xSocket ) );
345 
346     xSocket.bits.bIsIPv6 = pdTRUE_UNSIGNED;
347 
348     uxGetMinimumFreeNetworkBuffers_ExpectAndReturn( 0 );
349     uxGetNumberOfFreeNetworkBuffers_ExpectAndReturn( 0 );
350 
351     listLIST_IS_INITIALISED_ExpectAndReturn( &xBoundTCPSocketsList, pdTRUE );
352 
353     listGET_END_MARKER_ExpectAndReturn( &xBoundTCPSocketsList, &xLocalTCPItem );
354     listGET_END_MARKER_ExpectAndReturn( &xBoundUDPSocketsList, &xLocalUDPItem );
355 
356     /* First Iteration. */
357     listGET_HEAD_ENTRY_ExpectAndReturn( &xBoundTCPSocketsList, &xIterator );
358 
359     listGET_LIST_ITEM_OWNER_ExpectAndReturn( &xIterator, &xSocket );
360 
361     xTaskGetTickCount_ExpectAndReturn( 0x10 );
362 
363     /* TCP last iteration. */
364     listGET_NEXT_ExpectAndReturn( &xIterator, &xLocalTCPItem );
365 
366     /* UDP */
367     /* First Iteration. */
368     listGET_HEAD_ENTRY_ExpectAndReturn( &xBoundUDPSocketsList, &xIterator );
369 
370     /* Second Iteration. */
371     listGET_NEXT_ExpectAndReturn( &xIterator, &xIterator );
372 
373     /* TCP last iteration. */
374     listGET_NEXT_ExpectAndReturn( &xIterator, &xLocalUDPItem );
375 
376     vTCPNetStat();
377 }
378