1 /*
2 * FreeRTOS+TCP V3.1.0
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 * @file FreeRTOS_ICMP.c
30 * @brief Implements the Internet Control Message Protocol for the FreeRTOS+TCP network stack.
31 */
32
33 /* Standard includes. */
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 /* FreeRTOS includes. */
39 #include "FreeRTOS.h"
40 #include "task.h"
41 #include "queue.h"
42 #include "semphr.h"
43
44 /* FreeRTOS+TCP includes. */
45 #include "FreeRTOS_IP.h"
46 #include "FreeRTOS_IP_Timers.h"
47 #include "FreeRTOS_IP_Utils.h"
48 #include "FreeRTOS_Sockets.h"
49 #include "FreeRTOS_IP_Private.h"
50 #include "FreeRTOS_ARP.h"
51 #include "FreeRTOS_UDP_IP.h"
52 #include "FreeRTOS_DHCP.h"
53 #include "NetworkInterface.h"
54 #include "NetworkBufferManagement.h"
55 #include "FreeRTOS_DNS.h"
56
57 /*
58 * Utility functions for the light weight IP timers.
59 */
60 static void prvIPTimerStart( IPTimer_t * pxTimer,
61 TickType_t xTime );
62 static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer );
63 static void prvIPTimerReload( IPTimer_t * pxTimer,
64 TickType_t xTime );
65
66 /*
67 * A timer for each of the following processes, all of which need attention on a
68 * regular basis
69 */
70
71 /** @brief Timer to limit the maximum time a packet should be stored while
72 * awaiting an ARP resolution. */
73 static IPTimer_t xARPResolutionTimer;
74
75 /** @brief ARP timer, to check its table entries. */
76 static IPTimer_t xARPTimer;
77 #if ( ipconfigUSE_DHCP != 0 )
78 /** @brief DHCP timer, to send requests and to renew a reservation. */
79 static IPTimer_t xDHCPTimer;
80 #endif
81 #if ( ipconfigUSE_TCP != 0 )
82 /** @brief TCP timer, to check for timeouts, resends. */
83 static IPTimer_t xTCPTimer;
84 #endif
85 #if ( ipconfigDNS_USE_CALLBACKS != 0 )
86 /** @brief DNS timer, to check for timeouts when looking-up a domain. */
87 static IPTimer_t xDNSTimer;
88 #endif
89
90 /**
91 * @brief Calculate the maximum sleep time remaining. It will go through all
92 * timers to see which timer will expire first. That will be the amount
93 * of time to block in the next call to xQueueReceive().
94 *
95 * @return The maximum sleep time or ipconfigMAX_IP_TASK_SLEEP_TIME,
96 * whichever is smaller.
97 */
xCalculateSleepTime(void)98 TickType_t xCalculateSleepTime( void )
99 {
100 TickType_t uxMaximumSleepTime;
101
102 /* Start with the maximum sleep time, then check this against the remaining
103 * time in any other timers that are active. */
104 uxMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME;
105
106 if( xARPTimer.bActive != pdFALSE_UNSIGNED )
107 {
108 if( xARPTimer.ulRemainingTime < uxMaximumSleepTime )
109 {
110 uxMaximumSleepTime = xARPTimer.ulRemainingTime;
111 }
112 }
113
114 #if ( ipconfigUSE_DHCP == 1 )
115 {
116 if( xDHCPTimer.bActive != pdFALSE_UNSIGNED )
117 {
118 if( xDHCPTimer.ulRemainingTime < uxMaximumSleepTime )
119 {
120 uxMaximumSleepTime = xDHCPTimer.ulRemainingTime;
121 }
122 }
123 }
124 #endif /* ipconfigUSE_DHCP */
125
126 #if ( ipconfigUSE_TCP == 1 )
127 {
128 if( xTCPTimer.bActive != pdFALSE_UNSIGNED )
129 {
130 if( xTCPTimer.ulRemainingTime < uxMaximumSleepTime )
131 {
132 uxMaximumSleepTime = xTCPTimer.ulRemainingTime;
133 }
134 }
135 }
136 #endif
137
138 #if ( ipconfigDNS_USE_CALLBACKS != 0 )
139 {
140 if( xDNSTimer.bActive != pdFALSE_UNSIGNED )
141 {
142 if( xDNSTimer.ulRemainingTime < uxMaximumSleepTime )
143 {
144 uxMaximumSleepTime = xDNSTimer.ulRemainingTime;
145 }
146 }
147 }
148 #endif
149
150 return uxMaximumSleepTime;
151 }
152 /*-----------------------------------------------------------*/
153
154 /**
155 * @brief Check the network timers (ARP/DHCP/DNS/TCP) and if they are
156 * expired, send an event to the IP-Task.
157 */
vCheckNetworkTimers(void)158 void vCheckNetworkTimers( void )
159 {
160 /* Is it time for ARP processing? */
161 if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
162 {
163 ( void ) xSendEventToIPTask( eARPTimerEvent );
164 }
165
166 /* Is the ARP resolution timer expired? */
167 if( prvIPTimerCheck( &xARPResolutionTimer ) != pdFALSE )
168 {
169 if( pxARPWaitingNetworkBuffer != NULL )
170 {
171 /* Disable the ARP resolution timer. */
172 vIPSetARPResolutionTimerEnableState( pdFALSE );
173
174 /* We have waited long enough for the ARP response. Now, free the network
175 * buffer. */
176 vReleaseNetworkBufferAndDescriptor( pxARPWaitingNetworkBuffer );
177
178 /* Clear the pointer. */
179 pxARPWaitingNetworkBuffer = NULL;
180
181 iptraceDELAYED_ARP_TIMER_EXPIRED();
182 }
183 }
184
185 #if ( ipconfigUSE_DHCP == 1 )
186 {
187 /* Is it time for DHCP processing? */
188 if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )
189 {
190 ( void ) xSendDHCPEvent();
191 }
192 }
193 #endif /* ipconfigUSE_DHCP */
194
195 #if ( ipconfigDNS_USE_CALLBACKS != 0 )
196 {
197 /* Is it time for DNS processing? */
198 if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
199 {
200 vDNSCheckCallBack( NULL );
201 }
202 }
203 #endif /* ipconfigDNS_USE_CALLBACKS */
204
205 #if ( ipconfigUSE_TCP == 1 )
206 {
207 BaseType_t xWillSleep;
208 TickType_t xNextTime;
209 BaseType_t xCheckTCPSockets;
210
211 /* If the IP task has messages waiting to be processed then
212 * it will not sleep in any case. */
213 if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
214 {
215 xWillSleep = pdTRUE;
216 }
217 else
218 {
219 xWillSleep = pdFALSE;
220 }
221
222 /* Sockets need to be checked if the TCP timer has expired. */
223 xCheckTCPSockets = prvIPTimerCheck( &xTCPTimer );
224
225 /* Sockets will also be checked if there are TCP messages but the
226 * message queue is empty (indicated by xWillSleep being true). */
227 if( ( xProcessedTCPMessage != pdFALSE ) && ( xWillSleep != pdFALSE ) )
228 {
229 xCheckTCPSockets = pdTRUE;
230 }
231
232 if( xCheckTCPSockets != pdFALSE )
233 {
234 /* Attend to the sockets, returning the period after which the
235 * check must be repeated. */
236 xNextTime = xTCPTimerCheck( xWillSleep );
237 prvIPTimerStart( &xTCPTimer, xNextTime );
238 xProcessedTCPMessage = 0;
239 }
240 }
241
242 /* See if any socket was planned to be closed. */
243 vSocketCloseNextTime( NULL );
244
245 /* See if any reusable socket needs to go back to 'eTCP_LISTEN' state. */
246 vSocketListenNextTime( NULL );
247 #endif /* ipconfigUSE_TCP == 1 */
248 }
249 /*-----------------------------------------------------------*/
250
251 /**
252 * @brief Start an IP timer. The IP-task has its own implementation of a timer
253 * called 'IPTimer_t', which is based on the FreeRTOS 'TimeOut_t'.
254 *
255 * @param[in] pxTimer: Pointer to the IP timer. When zero, the timer is marked
256 * as expired.
257 * @param[in] xTime: Time to be loaded into the IP timer.
258 */
prvIPTimerStart(IPTimer_t * pxTimer,TickType_t xTime)259 static void prvIPTimerStart( IPTimer_t * pxTimer,
260 TickType_t xTime )
261 {
262 vTaskSetTimeOutState( &pxTimer->xTimeOut );
263 pxTimer->ulRemainingTime = xTime;
264
265 if( xTime == ( TickType_t ) 0 )
266 {
267 pxTimer->bExpired = pdTRUE_UNSIGNED;
268 }
269 else
270 {
271 pxTimer->bExpired = pdFALSE_UNSIGNED;
272 }
273
274 pxTimer->bActive = pdTRUE_UNSIGNED;
275 }
276 /*-----------------------------------------------------------*/
277
vIPTimerStartARPResolution(TickType_t xTime)278 void vIPTimerStartARPResolution( TickType_t xTime )
279 {
280 prvIPTimerStart( &( xARPResolutionTimer ), xTime );
281 }
282 /*-----------------------------------------------------------*/
283
284 /**
285 * @brief Sets the reload time of an IP timer and restarts it.
286 *
287 * @param[in] pxTimer: Pointer to the IP timer.
288 * @param[in] xTime: Time to be reloaded into the IP timer.
289 */
prvIPTimerReload(IPTimer_t * pxTimer,TickType_t xTime)290 static void prvIPTimerReload( IPTimer_t * pxTimer,
291 TickType_t xTime )
292 {
293 pxTimer->ulReloadTime = xTime;
294 prvIPTimerStart( pxTimer, xTime );
295 }
296 /*-----------------------------------------------------------*/
297
298 #if ( ipconfigUSE_TCP == 1 )
vTCPTimerReload(TickType_t xTime)299 void vTCPTimerReload( TickType_t xTime )
300 {
301 prvIPTimerReload( &xTCPTimer, xTime );
302 }
303 #endif
304 /*-----------------------------------------------------------*/
305
vARPTimerReload(TickType_t xTime)306 void vARPTimerReload( TickType_t xTime )
307 {
308 prvIPTimerReload( &xARPTimer, xTime );
309 }
310 /*-----------------------------------------------------------*/
311
312 #if ( ipconfigUSE_DHCP == 1 )
313
314 /**
315 * @brief Reload the DHCP timer.
316 *
317 * @param[in] ulLeaseTime: The reload value.
318 */
vDHCPTimerReload(TickType_t xLeaseTime)319 void vDHCPTimerReload( TickType_t xLeaseTime )
320 {
321 prvIPTimerReload( &xDHCPTimer, xLeaseTime );
322 }
323 #endif /* ipconfigUSE_DHCP */
324 /*-----------------------------------------------------------*/
325
326 #if ( ipconfigDNS_USE_CALLBACKS != 0 )
327
328 /**
329 * @brief Reload the DNS timer.
330 *
331 * @param[in] ulCheckTime: The reload value.
332 */
vDNSTimerReload(uint32_t ulCheckTime)333 void vDNSTimerReload( uint32_t ulCheckTime )
334 {
335 prvIPTimerReload( &xDNSTimer, ulCheckTime );
336 }
337 #endif /* ipconfigDNS_USE_CALLBACKS != 0 */
338 /*-----------------------------------------------------------*/
339
340 /**
341 * @brief Check the IP timer to see whether an IP event should be processed or not.
342 *
343 * @param[in] pxTimer: Pointer to the IP timer.
344 *
345 * @return If the timer is expired then pdTRUE is returned. Else pdFALSE.
346 */
prvIPTimerCheck(IPTimer_t * pxTimer)347 static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer )
348 {
349 BaseType_t xReturn;
350
351 if( pxTimer->bActive == pdFALSE_UNSIGNED )
352 {
353 /* The timer is not enabled. */
354 xReturn = pdFALSE;
355 }
356 else
357 {
358 /* The timer might have set the bExpired flag already, if not, check the
359 * value of xTimeOut against ulRemainingTime. */
360 if( pxTimer->bExpired == pdFALSE_UNSIGNED )
361 {
362 if( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE )
363 {
364 pxTimer->bExpired = pdTRUE_UNSIGNED;
365 }
366 }
367
368 if( pxTimer->bExpired != pdFALSE_UNSIGNED )
369 {
370 prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
371 xReturn = pdTRUE;
372 }
373 else
374 {
375 xReturn = pdFALSE;
376 }
377 }
378
379 return xReturn;
380 }
381 /*-----------------------------------------------------------*/
382
383 #if ( ipconfigUSE_TCP == 1 )
384
385 /**
386 * @brief Enable/disable the TCP timer.
387 *
388 * @param[in] xExpiredState: pdTRUE - set as expired; pdFALSE - set as non-expired.
389 */
vIPSetTCPTimerExpiredState(BaseType_t xExpiredState)390 void vIPSetTCPTimerExpiredState( BaseType_t xExpiredState )
391 {
392 xTCPTimer.bActive = pdTRUE_UNSIGNED;
393
394 if( xExpiredState != pdFALSE )
395 {
396 xTCPTimer.bExpired = pdTRUE_UNSIGNED;
397 }
398 else
399 {
400 xTCPTimer.bExpired = pdFALSE_UNSIGNED;
401 }
402 }
403 /*-----------------------------------------------------------*/
404 #endif /* if ( ipconfigUSE_TCP == 1 ) */
405
406 /**
407 * @brief Enable/disable the ARP timer.
408 *
409 * @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
410 */
vIPSetARPTimerEnableState(BaseType_t xEnableState)411 void vIPSetARPTimerEnableState( BaseType_t xEnableState )
412 {
413 if( xEnableState != pdFALSE )
414 {
415 xARPTimer.bActive = pdTRUE_UNSIGNED;
416 }
417 else
418 {
419 xARPTimer.bActive = pdFALSE_UNSIGNED;
420 }
421 }
422 /*-----------------------------------------------------------*/
423
424 /**
425 * @brief Enable or disable the ARP resolution timer.
426 *
427 * @param[in] xEnableState: pdTRUE if the timer must be enabled, pdFALSE otherwise.
428 */
vIPSetARPResolutionTimerEnableState(BaseType_t xEnableState)429 void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState )
430 {
431 if( xEnableState != pdFALSE )
432 {
433 xARPResolutionTimer.bActive = pdTRUE_UNSIGNED;
434 }
435 else
436 {
437 xARPResolutionTimer.bActive = pdFALSE_UNSIGNED;
438 }
439 }
440 /*-----------------------------------------------------------*/
441
442 #if ( ipconfigUSE_DHCP == 1 )
443
444 /**
445 * @brief Enable/disable the DHCP timer.
446 *
447 * @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
448 */
vIPSetDHCPTimerEnableState(BaseType_t xEnableState)449 void vIPSetDHCPTimerEnableState( BaseType_t xEnableState )
450 {
451 if( xEnableState != pdFALSE )
452 {
453 xDHCPTimer.bActive = pdTRUE_UNSIGNED;
454 }
455 else
456 {
457 xDHCPTimer.bActive = pdFALSE_UNSIGNED;
458 }
459 }
460 #endif /* ipconfigUSE_DHCP */
461 /*-----------------------------------------------------------*/
462
463 #if ( ipconfigDNS_USE_CALLBACKS == 1 )
464
465 /**
466 * @brief Enable/disable the DNS timer.
467 *
468 * @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
469 */
vIPSetDNSTimerEnableState(BaseType_t xEnableState)470 void vIPSetDNSTimerEnableState( BaseType_t xEnableState )
471 {
472 if( xEnableState != 0 )
473 {
474 xDNSTimer.bActive = pdTRUE_UNSIGNED;
475 }
476 else
477 {
478 xDNSTimer.bActive = pdFALSE_UNSIGNED;
479 }
480 }
481
482 #endif /* ipconfigDNS_USE_CALLBACKS == 1 */
483 /*-----------------------------------------------------------*/
484