xref: /FreeRTOS-Plus-TCP-v3.1.0/source/FreeRTOS_IP.c (revision 37bdfe577f3b728058de714e2e747d3c78803f26)
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_IP.c
30  * @brief Implements the basic functionality 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_ICMP.h"
47 #include "FreeRTOS_IP_Timers.h"
48 #include "FreeRTOS_IP_Utils.h"
49 #include "FreeRTOS_Sockets.h"
50 #include "FreeRTOS_IP_Private.h"
51 #include "FreeRTOS_ARP.h"
52 #include "FreeRTOS_UDP_IP.h"
53 #include "FreeRTOS_DHCP.h"
54 #include "NetworkInterface.h"
55 #include "NetworkBufferManagement.h"
56 #include "FreeRTOS_DNS.h"
57 
58 /* IPv4 multi-cast addresses range from 224.0.0.0.0 to 240.0.0.0. */
59 #define ipFIRST_MULTI_CAST_IPv4             0xE0000000U /**< Lower bound of the IPv4 multicast address. */
60 #define ipLAST_MULTI_CAST_IPv4              0xF0000000U /**< Higher bound of the IPv4 multicast address. */
61 
62 /* The first byte in the IPv4 header combines the IP version (4) with
63  * with the length of the IP header. */
64 #define ipIPV4_VERSION_HEADER_LENGTH_MIN    0x45U /**< Minimum IPv4 header length. */
65 #define ipIPV4_VERSION_HEADER_LENGTH_MAX    0x4FU /**< Maximum IPv4 header length. */
66 
67 /** @brief Maximum time to wait for an ARP resolution while holding a packet. */
68 #ifndef ipARP_RESOLUTION_MAX_DELAY
69     #define ipARP_RESOLUTION_MAX_DELAY    ( pdMS_TO_TICKS( 2000U ) )
70 #endif
71 
72 #ifndef iptraceIP_TASK_STARTING
73     #define iptraceIP_TASK_STARTING()    do {} while( ipFALSE_BOOL ) /**< Empty definition in case iptraceIP_TASK_STARTING is not defined. */
74 #endif
75 
76 #if ( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
77     /** @brief When initialising the TCP timer, give it an initial time-out of 1 second. */
78     #define ipTCP_TIMER_PERIOD_MS    ( 1000U )
79 #endif
80 
81 /** @brief Defines how often the ARP timer callback function is executed.  The time is
82  * shorter in the Windows simulator as simulated time is not real time. */
83 #ifndef ipARP_TIMER_PERIOD_MS
84     #ifdef _WINDOWS_
85         #define ipARP_TIMER_PERIOD_MS    ( 500U ) /* For windows simulator builds. */
86     #else
87         #define ipARP_TIMER_PERIOD_MS    ( 10000U )
88     #endif
89 #endif
90 
91 #if ( ipconfigUSE_TCP != 0 )
92 
93 /** @brief Set to a non-zero value if one or more TCP message have been processed
94  * within the last round. */
95     BaseType_t xProcessedTCPMessage;
96 #endif
97 
98 /** @brief If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
99  * driver will filter incoming packets and only pass the stack those packets it
100  * considers need processing.  In this case ipCONSIDER_FRAME_FOR_PROCESSING() can
101  * be #-defined away.  If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 0
102  * then the Ethernet driver will pass all received packets to the stack, and the
103  * stack must do the filtering itself.  In this case ipCONSIDER_FRAME_FOR_PROCESSING
104  * needs to call eConsiderFrameForProcessing.
105  */
106 #if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0
107     #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer )    eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
108 #else
109     #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer )    eProcessBuffer
110 #endif
111 /*-----------------------------------------------------------*/
112 
113 /** @brief The pointer to buffer with packet waiting for ARP resolution. */
114 NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer = NULL;
115 
116 /*-----------------------------------------------------------*/
117 
118 static void prvProcessIPEventsAndTimers( void );
119 
120 /*
121  * The main TCP/IP stack processing task.  This task receives commands/events
122  * from the network hardware drivers and tasks that are using sockets.  It also
123  * maintains a set of protocol timers.
124  */
125 static void prvIPTask( void * pvParameters );
126 
127 /*
128  * Called when new data is available from the network interface.
129  */
130 static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
131 
132 #if ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 )
133 
134 /*
135  * The stack will call this user hook for all Ethernet frames that it
136  * does not support, i.e. other than IPv4, IPv6 and ARP ( for the moment )
137  * If this hook returns eReleaseBuffer or eProcessBuffer, the stack will
138  * release and reuse the network buffer.  If this hook returns
139  * eReturnEthernetFrame, that means user code has reused the network buffer
140  * to generate a response and the stack will send that response out.
141  * If this hook returns eFrameConsumed, the user code has ownership of the
142  * network buffer and has to release it when it's done.
143  */
144     extern eFrameProcessingResult_t eApplicationProcessCustomFrameHook( NetworkBufferDescriptor_t * const pxNetworkBuffer );
145 #endif /* ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 ) */
146 
147 /*
148  * Process incoming IP packets.
149  */
150 static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket,
151                                                     NetworkBufferDescriptor_t * const pxNetworkBuffer );
152 
153 /*
154  * The network card driver has received a packet.  In the case that it is part
155  * of a linked packet chain, walk through it to handle every message.
156  */
157 static void prvHandleEthernetPacket( NetworkBufferDescriptor_t * pxBuffer );
158 
159 
160 /* The function 'prvAllowIPPacket()' checks if a packets should be processed. */
161 static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
162                                                   const NetworkBufferDescriptor_t * const pxNetworkBuffer,
163                                                   UBaseType_t uxHeaderLength );
164 
165 #if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
166 
167 /* Even when the driver takes care of checksum calculations,
168  *  the IP-task will still check if the length fields are OK. */
169     static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer,
170                                         size_t uxBufferLength );
171 #endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
172 /*-----------------------------------------------------------*/
173 
174 /** @brief The queue used to pass events into the IP-task for processing. */
175 QueueHandle_t xNetworkEventQueue = NULL;
176 
177 /** @brief The IP packet ID. */
178 uint16_t usPacketIdentifier = 0U;
179 
180 /** @brief For convenience, a MAC address of all 0xffs is defined const for quick
181  * reference. */
182 const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
183 
184 /** @brief Structure that stores the netmask, gateway address and DNS server addresses. */
185 NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 };
186 
187 /** @brief Default values for the above struct in case DHCP
188  * does not lead to a confirmed request. */
189 
190 /* MISRA Ref 8.9.1 [File scoped variables] */
191 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */
192 /* coverity[misra_c_2012_rule_8_9_violation] */
193 NetworkAddressingParameters_t xDefaultAddressing = { 0, 0, 0, 0, 0 };
194 
195 /** @brief Used to ensure network down events cannot be missed when they cannot be
196  * posted to the network event queue because the network event queue is already
197  * full. */
198 static volatile BaseType_t xNetworkDownEventPending = pdFALSE;
199 
200 /** @brief Stores the handle of the task that handles the stack.  The handle is used
201  * (indirectly) by some utility function to determine if the utility function is
202  * being called by a task (in which case it is ok to block) or by the IP task
203  * itself (in which case it is not ok to block). */
204 
205 static TaskHandle_t xIPTaskHandle = NULL;
206 
207 /** @brief Simple set to pdTRUE or pdFALSE depending on whether the network is up or
208  * down (connected, not connected) respectively. */
209 static BaseType_t xNetworkUp = pdFALSE;
210 
211 /** @brief Set to pdTRUE when the IP task is ready to start processing packets. */
212 static BaseType_t xIPTaskInitialised = pdFALSE;
213 
214 #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
215     /** @brief Keep track of the lowest amount of space in 'xNetworkEventQueue'. */
216     static UBaseType_t uxQueueMinimumSpace = ipconfigEVENT_QUEUE_LENGTH;
217 #endif
218 
219 /*-----------------------------------------------------------*/
220 
221 /* Coverity wants to make pvParameters const, which would make it incompatible. Leave the
222  * function signature as is. */
223 
224 /**
225  * @brief The IP task handles all requests from the user application and the
226  *        network interface. It receives messages through a FreeRTOS queue called
227  *        'xNetworkEventQueue'. prvIPTask() is the only task which has access to
228  *        the data of the IP-stack, and so it has no need of using mutexes.
229  *
230  * @param[in] pvParameters: Not used.
231  */
232 
233 /* MISRA Ref 8.13.1 [Not decorating a pointer to const parameter with const] */
234 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-813 */
235 /* coverity[misra_c_2012_rule_8_13_violation] */
prvIPTask(void * pvParameters)236 static void prvIPTask( void * pvParameters )
237 {
238     /* Just to prevent compiler warnings about unused parameters. */
239     ( void ) pvParameters;
240 
241     /* A possibility to set some additional task properties. */
242     iptraceIP_TASK_STARTING();
243 
244     /* Generate a dummy message to say that the network connection has gone
245      *  down.  This will cause this task to initialise the network interface.  After
246      *  this it is the responsibility of the network interface hardware driver to
247      *  send this message if a previously connected network is disconnected. */
248     FreeRTOS_NetworkDown();
249 
250     #if ( ipconfigUSE_TCP == 1 )
251         {
252             /* Initialise the TCP timer. */
253             vTCPTimerReload( pdMS_TO_TICKS( ipTCP_TIMER_PERIOD_MS ) );
254         }
255     #endif
256 
257     /* Mark the timer as inactive since we are not waiting on any ARP resolution as of now. */
258     vIPSetARPResolutionTimerEnableState( pdFALSE );
259 
260     /* Initialisation is complete and events can now be processed. */
261     xIPTaskInitialised = pdTRUE;
262 
263     FreeRTOS_debug_printf( ( "prvIPTask started\n" ) );
264 
265     /* Loop, processing IP events. */
266     while( ipFOREVER() == pdTRUE )
267     {
268         prvProcessIPEventsAndTimers();
269     }
270 }
271 /*-----------------------------------------------------------*/
272 
273 /**
274  * @brief Process the events sent to the IP task and process the timers.
275  */
prvProcessIPEventsAndTimers(void)276 static void prvProcessIPEventsAndTimers( void )
277 {
278     IPStackEvent_t xReceivedEvent;
279     TickType_t xNextIPSleep;
280     FreeRTOS_Socket_t * pxSocket;
281     struct freertos_sockaddr xAddress;
282 
283     ipconfigWATCHDOG_TIMER();
284 
285     /* Check the ARP, DHCP and TCP timers to see if there is any periodic
286      * or timeout processing to perform. */
287     vCheckNetworkTimers();
288 
289     /* Calculate the acceptable maximum sleep time. */
290     xNextIPSleep = xCalculateSleepTime();
291 
292     /* Wait until there is something to do. If the following call exits
293      * due to a time out rather than a message being received, set a
294      * 'NoEvent' value. */
295     if( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE )
296     {
297         xReceivedEvent.eEventType = eNoEvent;
298     }
299 
300     #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
301         {
302             if( xReceivedEvent.eEventType != eNoEvent )
303             {
304                 UBaseType_t uxCount;
305 
306                 uxCount = uxQueueSpacesAvailable( xNetworkEventQueue );
307 
308                 if( uxQueueMinimumSpace > uxCount )
309                 {
310                     uxQueueMinimumSpace = uxCount;
311                 }
312             }
313         }
314     #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
315 
316     iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType );
317 
318     switch( xReceivedEvent.eEventType )
319     {
320         case eNetworkDownEvent:
321             /* Attempt to establish a connection. */
322             xNetworkUp = pdFALSE;
323             prvProcessNetworkDownEvent();
324             break;
325 
326         case eNetworkRxEvent:
327 
328             /* The network hardware driver has received a new packet.  A
329              * pointer to the received buffer is located in the pvData member
330              * of the received event structure. */
331             prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) xReceivedEvent.pvData );
332             break;
333 
334         case eNetworkTxEvent:
335 
336            {
337                NetworkBufferDescriptor_t * pxDescriptor = ( NetworkBufferDescriptor_t * ) xReceivedEvent.pvData;
338 
339                /* Send a network packet. The ownership will  be transferred to
340                 * the driver, which will release it after delivery. */
341                iptraceNETWORK_INTERFACE_OUTPUT( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer );
342                ( void ) xNetworkInterfaceOutput( pxDescriptor, pdTRUE );
343            }
344 
345            break;
346 
347         case eARPTimerEvent:
348             /* The ARP timer has expired, process the ARP cache. */
349             vARPAgeCache();
350             break;
351 
352         case eSocketBindEvent:
353 
354             /* FreeRTOS_bind (a user API) wants the IP-task to bind a socket
355              * to a port. The port number is communicated in the socket field
356              * usLocalPort. vSocketBind() will actually bind the socket and the
357              * API will unblock as soon as the eSOCKET_BOUND event is
358              * triggered. */
359             pxSocket = ( ( FreeRTOS_Socket_t * ) xReceivedEvent.pvData );
360             xAddress.sin_addr = 0U; /* For the moment. */
361             xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );
362             pxSocket->usLocalPort = 0U;
363             ( void ) vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
364 
365             /* Before 'eSocketBindEvent' was sent it was tested that
366              * ( xEventGroup != NULL ) so it can be used now to wake up the
367              * user. */
368             pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_BOUND;
369             vSocketWakeUpUser( pxSocket );
370             break;
371 
372         case eSocketCloseEvent:
373 
374             /* The user API FreeRTOS_closesocket() has sent a message to the
375              * IP-task to actually close a socket. This is handled in
376              * vSocketClose().  As the socket gets closed, there is no way to
377              * report back to the API, so the API won't wait for the result */
378             ( void ) vSocketClose( ( ( FreeRTOS_Socket_t * ) xReceivedEvent.pvData ) );
379             break;
380 
381         case eStackTxEvent:
382 
383             /* The network stack has generated a packet to send.  A
384              * pointer to the generated buffer is located in the pvData
385              * member of the received event structure. */
386             vProcessGeneratedUDPPacket( ( NetworkBufferDescriptor_t * ) xReceivedEvent.pvData );
387             break;
388 
389         case eDHCPEvent:
390             /* The DHCP state machine needs processing. */
391             #if ( ipconfigUSE_DHCP == 1 )
392                 {
393                     uintptr_t uxState;
394                     eDHCPState_t eState;
395 
396                     /* MISRA Ref 11.6.1 [DHCP events and conversion to void] */
397                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-116 */
398                     /* coverity[misra_c_2012_rule_11_6_violation] */
399                     uxState = ( uintptr_t ) xReceivedEvent.pvData;
400                     /* MISRA Ref 10.5.1 [DHCP events Enum] */
401                     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-105 */
402                     /* coverity[misra_c_2012_rule_10_5_violation] */
403                     eState = ( eDHCPState_t ) uxState;
404 
405                     /* Process DHCP messages for a given end-point. */
406                     vDHCPProcess( pdFALSE, eState );
407                 }
408             #endif /* ipconfigUSE_DHCP */
409             break;
410 
411         case eSocketSelectEvent:
412 
413             /* FreeRTOS_select() has got unblocked by a socket event,
414              * vSocketSelect() will check which sockets actually have an event
415              * and update the socket field xSocketBits. */
416             #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
417                 #if ( ipconfigSELECT_USES_NOTIFY != 0 )
418                     {
419                         SocketSelectMessage_t * pxMessage = ( ( SocketSelectMessage_t * ) xReceivedEvent.pvData );
420                         vSocketSelect( pxMessage->pxSocketSet );
421                         ( void ) xTaskNotifyGive( pxMessage->xTaskhandle );
422                     }
423                 #else
424                     {
425                         vSocketSelect( ( ( SocketSelect_t * ) xReceivedEvent.pvData ) );
426                     }
427                 #endif /* ( ipconfigSELECT_USES_NOTIFY != 0 ) */
428             #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
429             break;
430 
431         case eSocketSignalEvent:
432             #if ( ipconfigSUPPORT_SIGNALS != 0 )
433 
434                 /* Some task wants to signal the user of this socket in
435                  * order to interrupt a call to recv() or a call to select(). */
436                 ( void ) FreeRTOS_SignalSocket( ( Socket_t ) xReceivedEvent.pvData );
437             #endif /* ipconfigSUPPORT_SIGNALS */
438             break;
439 
440         case eTCPTimerEvent:
441             #if ( ipconfigUSE_TCP == 1 )
442 
443                 /* Simply mark the TCP timer as expired so it gets processed
444                  * the next time prvCheckNetworkTimers() is called. */
445                 vIPSetTCPTimerExpiredState( pdTRUE );
446             #endif /* ipconfigUSE_TCP */
447             break;
448 
449         case eTCPAcceptEvent:
450 
451             /* The API FreeRTOS_accept() was called, the IP-task will now
452              * check if the listening socket (communicated in pvData) actually
453              * received a new connection. */
454             #if ( ipconfigUSE_TCP == 1 )
455                 pxSocket = ( ( FreeRTOS_Socket_t * ) xReceivedEvent.pvData );
456 
457                 if( xTCPCheckNewClient( pxSocket ) != pdFALSE )
458                 {
459                     pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT;
460                     vSocketWakeUpUser( pxSocket );
461                 }
462             #endif /* ipconfigUSE_TCP */
463             break;
464 
465         case eTCPNetStat:
466 
467             /* FreeRTOS_netstat() was called to have the IP-task print an
468              * overview of all sockets and their connections */
469             #if ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_PRINTF == 1 ) )
470                 vTCPNetStat();
471             #endif /* ipconfigUSE_TCP */
472             break;
473 
474         case eSocketSetDeleteEvent:
475             #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
476                 {
477                     SocketSelect_t * pxSocketSet = ( SocketSelect_t * ) ( xReceivedEvent.pvData );
478 
479                     iptraceMEM_STATS_DELETE( pxSocketSet );
480                     vEventGroupDelete( pxSocketSet->xSelectGroup );
481                     vPortFree( ( void * ) pxSocketSet );
482                 }
483             #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
484             break;
485 
486         case eNoEvent:
487             /* xQueueReceive() returned because of a normal time-out. */
488             break;
489 
490         default:
491             /* Should not get here. */
492             break;
493     }
494 
495     if( xNetworkDownEventPending != pdFALSE )
496     {
497         /* A network down event could not be posted to the network event
498          * queue because the queue was full.
499          * As this code runs in the IP-task, it can be done directly by
500          * calling prvProcessNetworkDownEvent(). */
501         prvProcessNetworkDownEvent();
502     }
503 }
504 /*-----------------------------------------------------------*/
505 
506 /**
507  * @brief The variable 'xIPTaskHandle' is declared static.  This function
508  *        gives read-only access to it.
509  *
510  * @return The handle of the IP-task.
511  */
FreeRTOS_GetIPTaskHandle(void)512 TaskHandle_t FreeRTOS_GetIPTaskHandle( void )
513 {
514     return xIPTaskHandle;
515 }
516 /*-----------------------------------------------------------*/
517 
518 /**
519  * @brief Perform all the required tasks when the network gets connected.
520  */
vIPNetworkUpCalls(void)521 void vIPNetworkUpCalls( void )
522 {
523     xNetworkUp = pdTRUE;
524 
525     #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
526         {
527             vApplicationIPNetworkEventHook( eNetworkUp );
528         }
529     #endif /* ipconfigUSE_NETWORK_EVENT_HOOK */
530 
531     #if ( ipconfigDNS_USE_CALLBACKS != 0 )
532         {
533             /* The following function is declared in FreeRTOS_DNS.c and 'private' to
534              * this library */
535             extern void vDNSInitialise( void );
536             vDNSInitialise();
537         }
538     #endif /* ipconfigDNS_USE_CALLBACKS != 0 */
539 
540     /* Set remaining time to 0 so it will become active immediately. */
541     vARPTimerReload( pdMS_TO_TICKS( ipARP_TIMER_PERIOD_MS ) );
542 }
543 /*-----------------------------------------------------------*/
544 
545 /**
546  * @brief The variable 'xNetworkDownEventPending' is declared static.  This function
547  *        gives read-only access to it.
548  *
549  * @return pdTRUE if there a network-down event pending. pdFALSE otherwise.
550  */
xIsNetworkDownEventPending(void)551 BaseType_t xIsNetworkDownEventPending( void )
552 {
553     return xNetworkDownEventPending;
554 }
555 /*-----------------------------------------------------------*/
556 
557 /**
558  * @brief Handle the incoming Ethernet packets.
559  *
560  * @param[in] pxBuffer: Linked/un-linked network buffer descriptor(s)
561  *                      to be processed.
562  */
prvHandleEthernetPacket(NetworkBufferDescriptor_t * pxBuffer)563 static void prvHandleEthernetPacket( NetworkBufferDescriptor_t * pxBuffer )
564 {
565     #if ( ipconfigUSE_LINKED_RX_MESSAGES == 0 )
566         {
567             /* When ipconfigUSE_LINKED_RX_MESSAGES is set to 0 then only one
568              * buffer will be sent at a time.  This is the default way for +TCP to pass
569              * messages from the MAC to the TCP/IP stack. */
570             prvProcessEthernetPacket( pxBuffer );
571         }
572     #else /* ipconfigUSE_LINKED_RX_MESSAGES */
573         {
574             NetworkBufferDescriptor_t * pxNextBuffer;
575 
576             /* An optimisation that is useful when there is high network traffic.
577              * Instead of passing received packets into the IP task one at a time the
578              * network interface can chain received packets together and pass them into
579              * the IP task in one go.  The packets are chained using the pxNextBuffer
580              * member.  The loop below walks through the chain processing each packet
581              * in the chain in turn. */
582 
583             /* While there is another packet in the chain. */
584             while( pxBuffer != NULL )
585             {
586                 /* Store a pointer to the buffer after pxBuffer for use later on. */
587                 pxNextBuffer = pxBuffer->pxNextBuffer;
588 
589                 /* Make it NULL to avoid using it later on. */
590                 pxBuffer->pxNextBuffer = NULL;
591 
592                 prvProcessEthernetPacket( pxBuffer );
593                 pxBuffer = pxNextBuffer;
594             }
595         }
596     #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
597 }
598 /*-----------------------------------------------------------*/
599 
600 /**
601  * @brief Send a network down event to the IP-task. If it fails to post a message,
602  *         the failure will be noted in the variable 'xNetworkDownEventPending'
603  *         and later on a 'network-down' event, it will be executed.
604  */
FreeRTOS_NetworkDown(void)605 void FreeRTOS_NetworkDown( void )
606 {
607     static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
608     const TickType_t xDontBlock = ( TickType_t ) 0;
609 
610     /* Simply send the network task the appropriate event. */
611     if( xSendEventStructToIPTask( &xNetworkDownEvent, xDontBlock ) != pdPASS )
612     {
613         /* Could not send the message, so it is still pending. */
614         xNetworkDownEventPending = pdTRUE;
615     }
616     else
617     {
618         /* Message was sent so it is not pending. */
619         xNetworkDownEventPending = pdFALSE;
620     }
621 
622     iptraceNETWORK_DOWN();
623 }
624 /*-----------------------------------------------------------*/
625 
626 /**
627  * @brief Utility function. Process Network Down event from ISR.
628  *        This function is supposed to be called form an ISR. It is recommended
629  * - *        use 'FreeRTOS_NetworkDown()', when calling from a normal task.
630  *
631  * @return If the event was processed successfully, then return pdTRUE.
632  *         Else pdFALSE.
633  */
FreeRTOS_NetworkDownFromISR(void)634 BaseType_t FreeRTOS_NetworkDownFromISR( void )
635 {
636     static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
637     BaseType_t xHigherPriorityTaskWoken = pdFALSE;
638 
639     /* Simply send the network task the appropriate event. */
640     if( xQueueSendToBackFromISR( xNetworkEventQueue, &xNetworkDownEvent, &xHigherPriorityTaskWoken ) != pdPASS )
641     {
642         xNetworkDownEventPending = pdTRUE;
643     }
644     else
645     {
646         xNetworkDownEventPending = pdFALSE;
647     }
648 
649     iptraceNETWORK_DOWN();
650 
651     return xHigherPriorityTaskWoken;
652 }
653 /*-----------------------------------------------------------*/
654 
655 /**
656  * @brief Obtain a buffer big enough for a UDP payload of given size.
657  *
658  * @param[in] uxRequestedSizeBytes: The size of the UDP payload.
659  * @param[in] uxBlockTimeTicks: Maximum amount of time for which this call
660  *            can block. This value is capped internally.
661  *
662  * @return If a buffer was created then the pointer to that buffer is returned,
663  *         else a NULL pointer is returned.
664  */
FreeRTOS_GetUDPPayloadBuffer(size_t uxRequestedSizeBytes,TickType_t uxBlockTimeTicks)665 void * FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes,
666                                      TickType_t uxBlockTimeTicks )
667 {
668     NetworkBufferDescriptor_t * pxNetworkBuffer;
669     void * pvReturn;
670     TickType_t uxBlockTime = uxBlockTimeTicks;
671 
672     /* Cap the block time.  The reason for this is explained where
673      * ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined (assuming an official
674      * FreeRTOSIPConfig.h header file is being used). */
675     if( uxBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
676     {
677         uxBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
678     }
679 
680     /* Obtain a network buffer with the required amount of storage. */
681     pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + uxRequestedSizeBytes, uxBlockTime );
682 
683     if( pxNetworkBuffer != NULL )
684     {
685         /* Set the actual packet size in case a bigger buffer was returned. */
686         pxNetworkBuffer->xDataLength = sizeof( UDPPacket_t ) + uxRequestedSizeBytes;
687         /* Skip 3 headers. */
688         pvReturn = &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( UDPPacket_t ) ] );
689     }
690     else
691     {
692         pvReturn = NULL;
693     }
694 
695     return ( void * ) pvReturn;
696 }
697 /*-----------------------------------------------------------*/
698 
699 /*_RB_ Should we add an error or assert if the task priorities are set such that the servers won't function as expected? */
700 
701 /*_HT_ There was a bug in FreeRTOS_TCP_IP.c that only occurred when the applications' priority was too high.
702  * As that bug has been repaired, there is not an urgent reason to warn.
703  * It is better though to use the advised priority scheme. */
704 
705 /**
706  * @brief Initialise the FreeRTOS-Plus-TCP network stack and initialise the IP-task.
707  *
708  * @param[in] ucIPAddress: Local IP address.
709  * @param[in] ucNetMask: Local netmask.
710  * @param[in] ucGatewayAddress: Local gateway address.
711  * @param[in] ucDNSServerAddress: Local DNS server address.
712  * @param[in] ucMACAddress: MAC address of the node.
713  *
714  * @return pdPASS if the task was successfully created and added to a ready
715  * list, otherwise an error code defined in the file projdefs.h
716  */
717 /* coverity[single_use] */
FreeRTOS_IPInit(const uint8_t ucIPAddress[ipIP_ADDRESS_LENGTH_BYTES],const uint8_t ucNetMask[ipIP_ADDRESS_LENGTH_BYTES],const uint8_t ucGatewayAddress[ipIP_ADDRESS_LENGTH_BYTES],const uint8_t ucDNSServerAddress[ipIP_ADDRESS_LENGTH_BYTES],const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES])718 BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
719                             const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
720                             const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
721                             const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
722                             const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] )
723 {
724     BaseType_t xReturn = pdFALSE;
725 
726     /* Check that the configuration values are correct and that the IP-task has not
727      * already been initialized. */
728     vPreCheckConfigs();
729 
730     /* Attempt to create the queue used to communicate with the IP task. */
731     #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
732         {
733             static StaticQueue_t xNetworkEventStaticQueue;
734             static uint8_t ucNetworkEventQueueStorageArea[ ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t ) ];
735             xNetworkEventQueue = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH,
736                                                      sizeof( IPStackEvent_t ),
737                                                      ucNetworkEventQueueStorageArea,
738                                                      &xNetworkEventStaticQueue );
739         }
740     #else
741         {
742             xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) );
743             configASSERT( xNetworkEventQueue != NULL );
744         }
745     #endif /* configSUPPORT_STATIC_ALLOCATION */
746 
747     if( xNetworkEventQueue != NULL )
748     {
749         #if ( configQUEUE_REGISTRY_SIZE > 0 )
750             {
751                 /* A queue registry is normally used to assist a kernel aware
752                  * debugger.  If one is in use then it will be helpful for the debugger
753                  * to show information about the network event queue. */
754                 vQueueAddToRegistry( xNetworkEventQueue, "NetEvnt" );
755             }
756         #endif /* configQUEUE_REGISTRY_SIZE */
757 
758         if( xNetworkBuffersInitialise() == pdPASS )
759         {
760             /* Store the local IP and MAC address. */
761             xNetworkAddressing.ulDefaultIPAddress = FreeRTOS_inet_addr_quick( ucIPAddress[ 0 ], ucIPAddress[ 1 ], ucIPAddress[ 2 ], ucIPAddress[ 3 ] );
762             xNetworkAddressing.ulNetMask = FreeRTOS_inet_addr_quick( ucNetMask[ 0 ], ucNetMask[ 1 ], ucNetMask[ 2 ], ucNetMask[ 3 ] );
763             xNetworkAddressing.ulGatewayAddress = FreeRTOS_inet_addr_quick( ucGatewayAddress[ 0 ], ucGatewayAddress[ 1 ], ucGatewayAddress[ 2 ], ucGatewayAddress[ 3 ] );
764             xNetworkAddressing.ulDNSServerAddress = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );
765             xNetworkAddressing.ulBroadcastAddress = ( xNetworkAddressing.ulDefaultIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
766 
767             ( void ) memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
768 
769             #if ipconfigUSE_DHCP == 1
770                 {
771                     /* The IP address is not set until DHCP completes. */
772                     *ipLOCAL_IP_ADDRESS_POINTER = 0x00U;
773                 }
774             #else
775                 {
776                     /* The IP address is set from the value passed in. */
777                     *ipLOCAL_IP_ADDRESS_POINTER = xNetworkAddressing.ulDefaultIPAddress;
778 
779                     /* Added to prevent ARP flood to gateway.  Ensure the
780                     * gateway is on the same subnet as the IP address. */
781                     if( xNetworkAddressing.ulGatewayAddress != 0U )
782                     {
783                         configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) );
784                     }
785                 }
786             #endif /* ipconfigUSE_DHCP == 1 */
787 
788             /* The MAC address is stored in the start of the default packet
789              * header fragment, which is used when sending UDP packets. */
790             ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
791 
792             /* Prepare the sockets interface. */
793             vNetworkSocketsInit();
794 
795             /* Create the task that processes Ethernet and stack events. */
796             #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
797                 {
798                     static StaticTask_t xIPTaskBuffer;
799                     static StackType_t xIPTaskStack[ ipconfigIP_TASK_STACK_SIZE_WORDS ];
800                     xIPTaskHandle = xTaskCreateStatic( prvIPTask,
801                                                        "IP-Task",
802                                                        ipconfigIP_TASK_STACK_SIZE_WORDS,
803                                                        NULL,
804                                                        ipconfigIP_TASK_PRIORITY,
805                                                        xIPTaskStack,
806                                                        &xIPTaskBuffer );
807 
808                     if( xIPTaskHandle != NULL )
809                     {
810                         xReturn = pdTRUE;
811                     }
812                 }
813             #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
814                 {
815                     xReturn = xTaskCreate( prvIPTask,
816                                            "IP-task",
817                                            ipconfigIP_TASK_STACK_SIZE_WORDS,
818                                            NULL,
819                                            ipconfigIP_TASK_PRIORITY,
820                                            &( xIPTaskHandle ) );
821                 }
822             #endif /* configSUPPORT_STATIC_ALLOCATION */
823         }
824         else
825         {
826             FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: xNetworkBuffersInitialise() failed\n" ) );
827 
828             /* Clean up. */
829             vQueueDelete( xNetworkEventQueue );
830             xNetworkEventQueue = NULL;
831         }
832     }
833     else
834     {
835         FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: Network event queue could not be created\n" ) );
836     }
837 
838     return xReturn;
839 }
840 /*-----------------------------------------------------------*/
841 
842 /**
843  * @brief Get the current address configuration. Only non-NULL pointers will
844  *        be filled in.
845  *
846  * @param[out] pulIPAddress: The current IP-address assigned.
847  * @param[out] pulNetMask: The netmask used for current subnet.
848  * @param[out] pulGatewayAddress: The gateway address.
849  * @param[out] pulDNSServerAddress: The DNS server address.
850  */
FreeRTOS_GetAddressConfiguration(uint32_t * pulIPAddress,uint32_t * pulNetMask,uint32_t * pulGatewayAddress,uint32_t * pulDNSServerAddress)851 void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress,
852                                        uint32_t * pulNetMask,
853                                        uint32_t * pulGatewayAddress,
854                                        uint32_t * pulDNSServerAddress )
855 {
856     /* Return the address configuration to the caller. */
857 
858     if( pulIPAddress != NULL )
859     {
860         *pulIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;
861     }
862 
863     if( pulNetMask != NULL )
864     {
865         *pulNetMask = xNetworkAddressing.ulNetMask;
866     }
867 
868     if( pulGatewayAddress != NULL )
869     {
870         *pulGatewayAddress = xNetworkAddressing.ulGatewayAddress;
871     }
872 
873     if( pulDNSServerAddress != NULL )
874     {
875         *pulDNSServerAddress = xNetworkAddressing.ulDNSServerAddress;
876     }
877 }
878 /*-----------------------------------------------------------*/
879 
880 /**
881  * @brief Set the current network address configuration. Only non-NULL pointers will
882  *        be used.
883  *
884  * @param[in] pulIPAddress: The current IP-address assigned.
885  * @param[in] pulNetMask: The netmask used for current subnet.
886  * @param[in] pulGatewayAddress: The gateway address.
887  * @param[in] pulDNSServerAddress: The DNS server address.
888  */
FreeRTOS_SetAddressConfiguration(const uint32_t * pulIPAddress,const uint32_t * pulNetMask,const uint32_t * pulGatewayAddress,const uint32_t * pulDNSServerAddress)889 void FreeRTOS_SetAddressConfiguration( const uint32_t * pulIPAddress,
890                                        const uint32_t * pulNetMask,
891                                        const uint32_t * pulGatewayAddress,
892                                        const uint32_t * pulDNSServerAddress )
893 {
894     /* Update the address configuration. */
895 
896     if( pulIPAddress != NULL )
897     {
898         *ipLOCAL_IP_ADDRESS_POINTER = *pulIPAddress;
899     }
900 
901     if( pulNetMask != NULL )
902     {
903         xNetworkAddressing.ulNetMask = *pulNetMask;
904     }
905 
906     if( pulGatewayAddress != NULL )
907     {
908         xNetworkAddressing.ulGatewayAddress = *pulGatewayAddress;
909     }
910 
911     if( pulDNSServerAddress != NULL )
912     {
913         xNetworkAddressing.ulDNSServerAddress = *pulDNSServerAddress;
914     }
915 }
916 /*-----------------------------------------------------------*/
917 
918 /**
919  * @brief Release the UDP payload buffer.
920  *
921  * @param[in] pvBuffer: Pointer to the UDP buffer that is to be released.
922  */
FreeRTOS_ReleaseUDPPayloadBuffer(void const * pvBuffer)923 void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer )
924 {
925     vReleaseNetworkBufferAndDescriptor( pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer ) );
926 }
927 /*-----------------------------------------------------------*/
928 
929 #if ( ipconfigUSE_TCP == 1 )
930 
931 /**
932  * @brief Release the memory that was previously obtained by calling FreeRTOS_recv()
933  *        with the flag 'FREERTOS_ZERO_COPY'.
934  *
935  * @param[in] xSocket: The socket that was read from.
936  * @param[in] pvBuffer: The buffer returned in the call to FreeRTOS_recv().
937  * @param[in] xByteCount: The number of bytes that have been used.
938  *
939  * @return pdPASS if the buffer was released successfully, otherwise pdFAIL is returned.
940  */
FreeRTOS_ReleaseTCPPayloadBuffer(Socket_t xSocket,void const * pvBuffer,BaseType_t xByteCount)941     BaseType_t FreeRTOS_ReleaseTCPPayloadBuffer( Socket_t xSocket,
942                                                  void const * pvBuffer,
943                                                  BaseType_t xByteCount )
944     {
945         BaseType_t xByteCountReleased;
946         BaseType_t xReturn = pdFAIL;
947         uint8_t * pucData;
948         size_t uxBytesAvailable = uxStreamBufferGetPtr( xSocket->u.xTCP.rxStream, &( pucData ) );
949 
950         /* Make sure the pointer is correct. */
951         configASSERT( pucData == ( uint8_t * ) pvBuffer );
952 
953         /* Avoid releasing more bytes than available. */
954         configASSERT( uxBytesAvailable >= ( size_t ) xByteCount );
955 
956         if( ( pucData == pvBuffer ) && ( uxBytesAvailable >= ( size_t ) xByteCount ) )
957         {
958             /* Call recv with NULL pointer to advance the circular buffer. */
959             xByteCountReleased = FreeRTOS_recv( xSocket,
960                                                 NULL,
961                                                 ( size_t ) xByteCount,
962                                                 FREERTOS_MSG_DONTWAIT );
963 
964             configASSERT( xByteCountReleased == xByteCount );
965 
966             if( xByteCountReleased == xByteCount )
967             {
968                 xReturn = pdPASS;
969             }
970         }
971 
972         return xReturn;
973     }
974 #endif /* ( ipconfigUSE_TCP == 1 ) */
975 /*-----------------------------------------------------------*/
976 
977 #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
978 
979 /**
980  * @brief Send a ping request to the given IP address. After receiving a reply,
981  *        IP-task will call a user-supplied function 'vApplicationPingReplyHook()'.
982  *
983  * @param[in] ulIPAddress: The IP address to which the ping is to be sent.
984  * @param[in] uxNumberOfBytesToSend: Number of bytes in the ping request.
985  * @param[in] uxBlockTimeTicks: Maximum number of ticks to wait.
986  *
987  * @return If successfully sent to IP task for processing then the sequence
988  *         number of the ping packet or else, pdFAIL.
989  */
FreeRTOS_SendPingRequest(uint32_t ulIPAddress,size_t uxNumberOfBytesToSend,TickType_t uxBlockTimeTicks)990     BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress,
991                                          size_t uxNumberOfBytesToSend,
992                                          TickType_t uxBlockTimeTicks )
993     {
994         NetworkBufferDescriptor_t * pxNetworkBuffer;
995         ICMPHeader_t * pxICMPHeader;
996         EthernetHeader_t * pxEthernetHeader;
997         BaseType_t xReturn = pdFAIL;
998         static uint16_t usSequenceNumber = 0;
999         uint8_t * pucChar;
1000         size_t uxTotalLength;
1001         IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
1002 
1003         uxTotalLength = uxNumberOfBytesToSend + sizeof( ICMPPacket_t );
1004         BaseType_t xEnoughSpace;
1005 
1006         if( uxNumberOfBytesToSend < ( ipconfigNETWORK_MTU - ( sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) ) ) )
1007         {
1008             xEnoughSpace = pdTRUE;
1009         }
1010         else
1011         {
1012             xEnoughSpace = pdFALSE;
1013         }
1014 
1015         if( ( uxGetNumberOfFreeNetworkBuffers() >= 4U ) && ( uxNumberOfBytesToSend >= 1U ) && ( xEnoughSpace != pdFALSE ) )
1016         {
1017             pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxTotalLength, uxBlockTimeTicks );
1018 
1019             if( pxNetworkBuffer != NULL )
1020             {
1021                 pxEthernetHeader = ( ( EthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer );
1022                 pxEthernetHeader->usFrameType = ipIPv4_FRAME_TYPE;
1023 
1024                 pxICMPHeader = ( ( ICMPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] ) );
1025                 usSequenceNumber++;
1026 
1027                 /* Fill in the basic header information. */
1028                 pxICMPHeader->ucTypeOfMessage = ipICMP_ECHO_REQUEST;
1029                 pxICMPHeader->ucTypeOfService = 0;
1030                 pxICMPHeader->usIdentifier = usSequenceNumber;
1031                 pxICMPHeader->usSequenceNumber = usSequenceNumber;
1032 
1033                 /* Find the start of the data. */
1034                 pucChar = ( uint8_t * ) pxICMPHeader;
1035                 pucChar = &( pucChar[ sizeof( ICMPHeader_t ) ] );
1036 
1037                 /* Just memset the data to a fixed value. */
1038                 ( void ) memset( pucChar, ( int ) ipECHO_DATA_FILL_BYTE, uxNumberOfBytesToSend );
1039 
1040                 /* The message is complete, IP and checksum's are handled by
1041                  * vProcessGeneratedUDPPacket */
1042                 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = FREERTOS_SO_UDPCKSUM_OUT;
1043                 pxNetworkBuffer->ulIPAddress = ulIPAddress;
1044                 pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA;
1045                 /* xDataLength is the size of the total packet, including the Ethernet header. */
1046                 pxNetworkBuffer->xDataLength = uxTotalLength;
1047 
1048                 /* Send to the stack. */
1049                 xStackTxEvent.pvData = pxNetworkBuffer;
1050 
1051                 if( xSendEventStructToIPTask( &( xStackTxEvent ), uxBlockTimeTicks ) != pdPASS )
1052                 {
1053                     vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
1054                     iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
1055                 }
1056                 else
1057                 {
1058                     xReturn = ( BaseType_t ) usSequenceNumber;
1059                 }
1060             }
1061         }
1062         else
1063         {
1064             /* The requested number of bytes will not fit in the available space
1065              * in the network buffer. */
1066         }
1067 
1068         return xReturn;
1069     }
1070 
1071 #endif /* ipconfigSUPPORT_OUTGOING_PINGS == 1 */
1072 /*-----------------------------------------------------------*/
1073 
1074 /**
1075  * @brief Send an event to the IP task. It calls 'xSendEventStructToIPTask' internally.
1076  *
1077  * @param[in] eEvent: The event to be sent.
1078  *
1079  * @return pdPASS if the event was sent (or the desired effect was achieved). Else, pdFAIL.
1080  */
xSendEventToIPTask(eIPEvent_t eEvent)1081 BaseType_t xSendEventToIPTask( eIPEvent_t eEvent )
1082 {
1083     IPStackEvent_t xEventMessage;
1084     const TickType_t xDontBlock = ( TickType_t ) 0;
1085 
1086     xEventMessage.eEventType = eEvent;
1087     xEventMessage.pvData = ( void * ) NULL;
1088 
1089     return xSendEventStructToIPTask( &xEventMessage, xDontBlock );
1090 }
1091 /*-----------------------------------------------------------*/
1092 
1093 /**
1094  * @brief Send an event (in form of struct) to the IP task to be processed.
1095  *
1096  * @param[in] pxEvent: The event to be sent.
1097  * @param[in] uxTimeout: Timeout for waiting in case the queue is full. 0 for non-blocking calls.
1098  *
1099  * @return pdPASS if the event was sent (or the desired effect was achieved). Else, pdFAIL.
1100  */
xSendEventStructToIPTask(const IPStackEvent_t * pxEvent,TickType_t uxTimeout)1101 BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent,
1102                                      TickType_t uxTimeout )
1103 {
1104     BaseType_t xReturn, xSendMessage;
1105     TickType_t uxUseTimeout = uxTimeout;
1106 
1107     if( ( xIPIsNetworkTaskReady() == pdFALSE ) && ( pxEvent->eEventType != eNetworkDownEvent ) )
1108     {
1109         /* Only allow eNetworkDownEvent events if the IP task is not ready
1110          * yet.  Not going to attempt to send the message so the send failed. */
1111         xReturn = pdFAIL;
1112     }
1113     else
1114     {
1115         xSendMessage = pdTRUE;
1116 
1117         #if ( ipconfigUSE_TCP == 1 )
1118             {
1119                 if( pxEvent->eEventType == eTCPTimerEvent )
1120                 {
1121                     /* TCP timer events are sent to wake the timer task when
1122                      * xTCPTimer has expired, but there is no point sending them if the
1123                      * IP task is already awake processing other message. */
1124                     vIPSetTCPTimerExpiredState( pdTRUE );
1125 
1126                     if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0U )
1127                     {
1128                         /* Not actually going to send the message but this is not a
1129                          * failure as the message didn't need to be sent. */
1130                         xSendMessage = pdFALSE;
1131                     }
1132                 }
1133             }
1134         #endif /* ipconfigUSE_TCP */
1135 
1136         if( xSendMessage != pdFALSE )
1137         {
1138             /* The IP task cannot block itself while waiting for itself to
1139              * respond. */
1140             if( ( xIsCallingFromIPTask() == pdTRUE ) && ( uxUseTimeout > ( TickType_t ) 0U ) )
1141             {
1142                 uxUseTimeout = ( TickType_t ) 0;
1143             }
1144 
1145             xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, uxUseTimeout );
1146 
1147             if( xReturn == pdFAIL )
1148             {
1149                 /* A message should have been sent to the IP task, but wasn't. */
1150                 FreeRTOS_debug_printf( ( "xSendEventStructToIPTask: CAN NOT ADD %d\n", pxEvent->eEventType ) );
1151                 iptraceSTACK_TX_EVENT_LOST( pxEvent->eEventType );
1152             }
1153         }
1154         else
1155         {
1156             /* It was not necessary to send the message to process the event so
1157              * even though the message was not sent the call was successful. */
1158             xReturn = pdPASS;
1159         }
1160     }
1161 
1162     return xReturn;
1163 }
1164 /*-----------------------------------------------------------*/
1165 
1166 /**
1167  * @brief Decide whether this packet should be processed or not based on the IP address in the packet.
1168  *
1169  * @param[in] pucEthernetBuffer: The ethernet packet under consideration.
1170  *
1171  * @return Enum saying whether to release or to process the packet.
1172  */
eConsiderFrameForProcessing(const uint8_t * const pucEthernetBuffer)1173 eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer )
1174 {
1175     eFrameProcessingResult_t eReturn;
1176     const EthernetHeader_t * pxEthernetHeader;
1177 
1178     /* Map the buffer onto Ethernet Header struct for easy access to fields. */
1179 
1180     /* MISRA Ref 11.3.1 [Misaligned access] */
1181     /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1182     /* coverity[misra_c_2012_rule_11_3_violation] */
1183     pxEthernetHeader = ( ( const EthernetHeader_t * ) pucEthernetBuffer );
1184 
1185     if( memcmp( ipLOCAL_MAC_ADDRESS, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
1186     {
1187         /* The packet was directed to this node - process it. */
1188         eReturn = eProcessBuffer;
1189     }
1190     else if( memcmp( xBroadcastMACAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
1191     {
1192         /* The packet was a broadcast - process it. */
1193         eReturn = eProcessBuffer;
1194     }
1195     else
1196     #if ( ipconfigUSE_LLMNR == 1 )
1197         if( memcmp( xLLMNR_MacAdress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
1198         {
1199             /* The packet is a request for LLMNR - process it. */
1200             eReturn = eProcessBuffer;
1201         }
1202         else
1203     #endif /* ipconfigUSE_LLMNR */
1204     {
1205         /* The packet was not a broadcast, or for this node, just release
1206          * the buffer without taking any other action. */
1207         eReturn = eReleaseBuffer;
1208     }
1209 
1210     #if ( ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1 )
1211         {
1212             uint16_t usFrameType;
1213 
1214             if( eReturn == eProcessBuffer )
1215             {
1216                 usFrameType = pxEthernetHeader->usFrameType;
1217                 usFrameType = FreeRTOS_ntohs( usFrameType );
1218 
1219                 if( usFrameType <= 0x600U )
1220                 {
1221                     /* Not an Ethernet II frame. */
1222                     eReturn = eReleaseBuffer;
1223                 }
1224             }
1225         }
1226     #endif /* ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1  */
1227 
1228     return eReturn;
1229 }
1230 /*-----------------------------------------------------------*/
1231 
1232 /**
1233  * @brief Process the Ethernet packet.
1234  *
1235  * @param[in,out] pxNetworkBuffer: the network buffer containing the ethernet packet. If the
1236  *                                 buffer is large enough, it may be reused to send a reply.
1237  */
prvProcessEthernetPacket(NetworkBufferDescriptor_t * const pxNetworkBuffer)1238 static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
1239 {
1240     const EthernetHeader_t * pxEthernetHeader;
1241     eFrameProcessingResult_t eReturned = eReleaseBuffer;
1242 
1243     configASSERT( pxNetworkBuffer != NULL );
1244 
1245     iptraceNETWORK_INTERFACE_INPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
1246 
1247     /* Interpret the Ethernet frame. */
1248     if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
1249     {
1250         eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
1251 
1252         /* Map the buffer onto the Ethernet Header struct for easy access to the fields. */
1253 
1254         /* MISRA Ref 11.3.1 [Misaligned access] */
1255         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1256         /* coverity[misra_c_2012_rule_11_3_violation] */
1257         pxEthernetHeader = ( ( const EthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer );
1258 
1259         /* The condition "eReturned == eProcessBuffer" must be true. */
1260         #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
1261             if( eReturned == eProcessBuffer )
1262         #endif
1263         {
1264             /* Interpret the received Ethernet packet. */
1265             switch( pxEthernetHeader->usFrameType )
1266             {
1267                 case ipARP_FRAME_TYPE:
1268 
1269                     /* The Ethernet frame contains an ARP packet. */
1270                     if( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) )
1271                     {
1272                         /* MISRA Ref 11.3.1 [Misaligned access] */
1273                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1274                         /* coverity[misra_c_2012_rule_11_3_violation] */
1275                         eReturned = eARPProcessPacket( ( ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ) );
1276                     }
1277                     else
1278                     {
1279                         eReturned = eReleaseBuffer;
1280                     }
1281 
1282                     break;
1283 
1284                 case ipIPv4_FRAME_TYPE:
1285 
1286                     /* The Ethernet frame contains an IP packet. */
1287                     if( pxNetworkBuffer->xDataLength >= sizeof( IPPacket_t ) )
1288                     {
1289                         /* MISRA Ref 11.3.1 [Misaligned access] */
1290                         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1291                         /* coverity[misra_c_2012_rule_11_3_violation] */
1292                         eReturned = prvProcessIPPacket( ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer );
1293                     }
1294                     else
1295                     {
1296                         eReturned = eReleaseBuffer;
1297                     }
1298 
1299                     break;
1300 
1301                 default:
1302                     #if ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 )
1303                         /* Custom frame handler. */
1304                         eReturned = eApplicationProcessCustomFrameHook( pxNetworkBuffer );
1305                     #else
1306                         /* No other packet types are handled.  Nothing to do. */
1307                         eReturned = eReleaseBuffer;
1308                     #endif
1309                     break;
1310             }
1311         }
1312     }
1313 
1314     /* Perform any actions that resulted from processing the Ethernet frame. */
1315     switch( eReturned )
1316     {
1317         case eReturnEthernetFrame:
1318 
1319             /* The Ethernet frame will have been updated (maybe it was
1320              * an ARP request or a PING request?) and should be sent back to
1321              * its source. */
1322             vReturnEthernetFrame( pxNetworkBuffer, pdTRUE );
1323 
1324             /* parameter pdTRUE: the buffer must be released once
1325              * the frame has been transmitted */
1326             break;
1327 
1328         case eFrameConsumed:
1329 
1330             /* The frame is in use somewhere, don't release the buffer
1331              * yet. */
1332             break;
1333 
1334         case eWaitingARPResolution:
1335 
1336             if( pxARPWaitingNetworkBuffer == NULL )
1337             {
1338                 pxARPWaitingNetworkBuffer = pxNetworkBuffer;
1339                 vIPTimerStartARPResolution( ipARP_RESOLUTION_MAX_DELAY );
1340 
1341                 iptraceDELAYED_ARP_REQUEST_STARTED();
1342             }
1343             else
1344             {
1345                 /* We are already waiting on one ARP resolution. This frame will be dropped. */
1346                 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
1347 
1348                 iptraceDELAYED_ARP_BUFFER_FULL();
1349             }
1350 
1351             break;
1352 
1353         case eReleaseBuffer:
1354         case eProcessBuffer:
1355         default:
1356 
1357             /* The frame is not being used anywhere, and the
1358              * NetworkBufferDescriptor_t structure containing the frame should
1359              * just be released back to the list of free buffers. */
1360             vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
1361             break;
1362     }
1363 }
1364 /*-----------------------------------------------------------*/
1365 
1366 /**
1367  * @brief Is the IP address an IPv4 multicast address.
1368  *
1369  * @param[in] ulIPAddress: The IP address being checked.
1370  *
1371  * @return pdTRUE if the IP address is a multicast address or else, pdFALSE.
1372  */
xIsIPv4Multicast(uint32_t ulIPAddress)1373 BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress )
1374 {
1375     BaseType_t xReturn;
1376     uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress );
1377 
1378     if( ( ulIP >= ipFIRST_MULTI_CAST_IPv4 ) && ( ulIP < ipLAST_MULTI_CAST_IPv4 ) )
1379     {
1380         xReturn = pdTRUE;
1381     }
1382     else
1383     {
1384         xReturn = pdFALSE;
1385     }
1386 
1387     return xReturn;
1388 }
1389 /*-----------------------------------------------------------*/
1390 
1391 /**
1392  * @brief Check whether this IP packet is to be allowed or to be dropped.
1393  *
1394  * @param[in] pxIPPacket: The IP packet under consideration.
1395  * @param[in] pxNetworkBuffer: The whole network buffer.
1396  * @param[in] uxHeaderLength: The length of the header.
1397  *
1398  * @return Whether the packet should be processed or dropped.
1399  */
prvAllowIPPacket(const IPPacket_t * const pxIPPacket,const NetworkBufferDescriptor_t * const pxNetworkBuffer,UBaseType_t uxHeaderLength)1400 static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
1401                                                   const NetworkBufferDescriptor_t * const pxNetworkBuffer,
1402                                                   UBaseType_t uxHeaderLength )
1403 {
1404     eFrameProcessingResult_t eReturn = eProcessBuffer;
1405 
1406     #if ( ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )
1407         const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
1408     #else
1409 
1410         /* or else, the parameter won't be used and the function will be optimised
1411          * away */
1412         ( void ) pxIPPacket;
1413     #endif
1414 
1415     #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )
1416         {
1417             /* In systems with a very small amount of RAM, it might be advantageous
1418              * to have incoming messages checked earlier, by the network card driver.
1419              * This method may decrease the usage of sparse network buffers. */
1420             uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
1421             uint32_t ulSourceIPAddress = pxIPHeader->ulSourceIPAddress;
1422 
1423             /* Ensure that the incoming packet is not fragmented because the stack
1424              * doesn't not support IP fragmentation. All but the last fragment coming in will have their
1425              * "more fragments" flag set and the last fragment will have a non-zero offset.
1426              * We need to drop the packet in either of those cases. */
1427             if( ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) || ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_FLAGS_MORE_FRAGMENTS ) != 0U ) )
1428             {
1429                 /* Can not handle, fragmented packet. */
1430                 eReturn = eReleaseBuffer;
1431             }
1432 
1433             /* Test if the length of the IP-header is between 20 and 60 bytes,
1434              * and if the IP-version is 4. */
1435             else if( ( pxIPHeader->ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
1436                      ( pxIPHeader->ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
1437             {
1438                 /* Can not handle, unknown or invalid header version. */
1439                 eReturn = eReleaseBuffer;
1440             }
1441             /* Is the packet for this IP address? */
1442             else if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
1443                      /* Is it the global broadcast address 255.255.255.255 ? */
1444                      ( ulDestinationIPAddress != ipBROADCAST_IP_ADDRESS ) &&
1445                      /* Is it a specific broadcast address 192.168.1.255 ? */
1446                      ( ulDestinationIPAddress != xNetworkAddressing.ulBroadcastAddress ) &&
1447                      #if ( ipconfigUSE_LLMNR == 1 )
1448                          /* Is it the LLMNR multicast address? */
1449                          ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
1450                      #endif
1451                      /* Or (during DHCP negotiation) we have no IP-address yet? */
1452                      ( *ipLOCAL_IP_ADDRESS_POINTER != 0U ) )
1453             {
1454                 /* Packet is not for this node, release it */
1455                 eReturn = eReleaseBuffer;
1456             }
1457             /* Is the source address correct? */
1458             else if( ( FreeRTOS_ntohl( ulSourceIPAddress ) & 0xffU ) == 0xffU )
1459             {
1460                 /* The source address cannot be broadcast address. Replying to this
1461                  * packet may cause network storms. Drop the packet. */
1462                 eReturn = eReleaseBuffer;
1463             }
1464             else if( ( memcmp( xBroadcastMACAddress.ucBytes,
1465                                pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes,
1466                                sizeof( MACAddress_t ) ) == 0 ) &&
1467                      ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xffU ) != 0xffU ) )
1468             {
1469                 /* Ethernet address is a broadcast address, but the IP address is not a
1470                  * broadcast address. */
1471                 eReturn = eReleaseBuffer;
1472             }
1473             else if( memcmp( xBroadcastMACAddress.ucBytes,
1474                              pxIPPacket->xEthernetHeader.xSourceAddress.ucBytes,
1475                              sizeof( MACAddress_t ) ) == 0 )
1476             {
1477                 /* Ethernet source is a broadcast address. Drop the packet. */
1478                 eReturn = eReleaseBuffer;
1479             }
1480             else if( xIsIPv4Multicast( ulSourceIPAddress ) == pdTRUE )
1481             {
1482                 /* Source is a multicast IP address. Drop the packet in conformity with RFC 1112 section 7.2. */
1483                 eReturn = eReleaseBuffer;
1484             }
1485             else
1486             {
1487                 /* Packet is not fragmented, destination is this device, source IP and MAC
1488                  * addresses are correct. */
1489             }
1490         }
1491     #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
1492 
1493     #if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 )
1494         {
1495             /* Some drivers of NIC's with checksum-offloading will enable the above
1496              * define, so that the checksum won't be checked again here */
1497             if( eReturn == eProcessBuffer )
1498             {
1499                 /* Is the IP header checksum correct?
1500                  *
1501                  * NOTE: When the checksum of IP header is calculated while not omitting
1502                  * the checksum field, the resulting value of the checksum always is 0xffff
1503                  * which is denoted by ipCORRECT_CRC. See this wiki for more information:
1504                  * https://en.wikipedia.org/wiki/IPv4_header_checksum#Verifying_the_IPv4_header_checksum
1505                  * and this RFC: https://tools.ietf.org/html/rfc1624#page-4
1506                  */
1507                 if( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC )
1508                 {
1509                     /* Check sum in IP-header not correct. */
1510                     eReturn = eReleaseBuffer;
1511                 }
1512                 /* Is the upper-layer checksum (TCP/UDP/ICMP) correct? */
1513                 else if( usGenerateProtocolChecksum( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength, pdFALSE ) != ipCORRECT_CRC )
1514                 {
1515                     /* Protocol checksum not accepted. */
1516                     eReturn = eReleaseBuffer;
1517                 }
1518                 else
1519                 {
1520                     /* The checksum of the received packet is OK. */
1521                 }
1522             }
1523         }
1524     #else /* if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) */
1525         {
1526             if( eReturn == eProcessBuffer )
1527             {
1528                 if( xCheckSizeFields( ( uint8_t * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength ) != pdPASS )
1529                 {
1530                     /* Some of the length checks were not successful. */
1531                     eReturn = eReleaseBuffer;
1532                 }
1533             }
1534 
1535             #if ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 )
1536                 {
1537                     /* Check if this is a UDP packet without a checksum. */
1538                     if( eReturn == eProcessBuffer )
1539                     {
1540                         /* ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS is defined as 0,
1541                          * and so UDP packets carrying a protocol checksum of 0, will
1542                          * be dropped. */
1543 
1544                         /* Identify the next protocol. */
1545                         if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
1546                         {
1547                             const ProtocolPacket_t * pxProtPack;
1548 
1549                             /* pxProtPack will point to the offset were the protocols begin. */
1550 
1551                             /* MISRA Ref 11.3.1 [Misaligned access] */
1552                             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1553                             /* coverity[misra_c_2012_rule_11_3_violation] */
1554                             pxProtPack = ( ( ProtocolPacket_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) );
1555 
1556                             if( pxProtPack->xUDPPacket.xUDPHeader.usChecksum == ( uint16_t ) 0U )
1557                             {
1558                                 #if ( ipconfigHAS_PRINTF != 0 )
1559                                     {
1560                                         static BaseType_t xCount = 0;
1561 
1562                                         /* Exclude this from branch coverage as this is only used for debugging. */
1563                                         if( xCount < 5 ) /* LCOV_EXCL_BR_LINE */
1564                                         {
1565                                             FreeRTOS_printf( ( "prvAllowIPPacket: UDP packet from %xip without CRC dropped\n",
1566                                                                FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ) ) );
1567                                             xCount++;
1568                                         }
1569                                     }
1570                                 #endif /* ( ipconfigHAS_PRINTF != 0 ) */
1571 
1572                                 /* Protocol checksum not accepted. */
1573                                 eReturn = eReleaseBuffer;
1574                             }
1575                         }
1576                     }
1577                 }
1578             #endif /* ( ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS == 0 ) */
1579 
1580             /* to avoid warning unused parameters */
1581             ( void ) uxHeaderLength;
1582         }
1583     #endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */
1584 
1585     return eReturn;
1586 }
1587 /*-----------------------------------------------------------*/
1588 
1589 /**
1590  * @brief Process an IP-packet.
1591  *
1592  * @param[in] pxIPPacket: The IP packet to be processed.
1593  * @param[in] pxNetworkBuffer: The networkbuffer descriptor having the IP packet.
1594  *
1595  * @return An enum to show whether the packet should be released/kept/processed etc.
1596  */
prvProcessIPPacket(IPPacket_t * pxIPPacket,NetworkBufferDescriptor_t * const pxNetworkBuffer)1597 static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket,
1598                                                     NetworkBufferDescriptor_t * const pxNetworkBuffer )
1599 {
1600     eFrameProcessingResult_t eReturn;
1601     IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
1602     size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
1603     UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( uxLength & 0x0FU ) << 2 );
1604     uint8_t ucProtocol;
1605 
1606     /* Bound the calculated header length: take away the Ethernet header size,
1607      * then check if the IP header is claiming to be longer than the remaining
1608      * total packet size. Also check for minimal header field length. */
1609     if( ( uxHeaderLength > ( pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ) ) ||
1610         ( uxHeaderLength < ipSIZE_OF_IPv4_HEADER ) )
1611     {
1612         eReturn = eReleaseBuffer;
1613     }
1614     else
1615     {
1616         ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
1617         /* Check if the IP headers are acceptable and if it has our destination. */
1618         eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
1619 
1620         /* MISRA Ref 14.3.1 [Configuration dependent invariant] */
1621         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-143 */
1622         /* coverity[misra_c_2012_rule_14_3_violation] */
1623         /* coverity[cond_const] */
1624         if( eReturn == eProcessBuffer )
1625         {
1626             /* Are there IP-options. */
1627             if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
1628             {
1629                 /* The size of the IP-header is larger than 20 bytes.
1630                  * The extra space is used for IP-options. */
1631                 #if ( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 )
1632                     {
1633                         /* All structs of headers expect a IP header size of 20 bytes
1634                          * IP header options were included, we'll ignore them and cut them out. */
1635                         const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
1636                         /* From: the previous start of UDP/ICMP/TCP data. */
1637                         const uint8_t * pucSource = ( const uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + uxHeaderLength ] );
1638                         /* To: the usual start of UDP/ICMP/TCP data at offset 20 (decimal ) from IP header. */
1639                         uint8_t * pucTarget = ( uint8_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER ] );
1640                         /* How many: total length minus the options and the lower headers. */
1641                         const size_t xMoveLen = pxNetworkBuffer->xDataLength - ( optlen + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_ETH_HEADER );
1642 
1643                         ( void ) memmove( pucTarget, pucSource, xMoveLen );
1644                         pxNetworkBuffer->xDataLength -= optlen;
1645                         pxIPHeader->usLength = FreeRTOS_htons( FreeRTOS_ntohs( pxIPHeader->usLength ) - optlen );
1646 
1647                         /* Rewrite the Version/IHL byte to indicate that this packet has no IP options. */
1648                         pxIPHeader->ucVersionHeaderLength = ( pxIPHeader->ucVersionHeaderLength & 0xF0U ) | /* High nibble is the version. */
1649                                                             ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0FU );
1650                     }
1651                 #else /* if ( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 ) */
1652                     {
1653                         /* 'ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS' is not set, so packets carrying
1654                          * IP-options will be dropped. */
1655                         eReturn = eReleaseBuffer;
1656                     }
1657                 #endif /* if ( ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS != 0 ) */
1658             }
1659 
1660             /* MISRA Ref 14.3.1 [Configuration dependent invariant] */
1661             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-143 */
1662             /* coverity[misra_c_2012_rule_14_3_violation] */
1663             /* coverity[const] */
1664             if( eReturn != eReleaseBuffer )
1665             {
1666                 /* Add the IP and MAC addresses to the ARP table if they are not
1667                  * already there - otherwise refresh the age of the existing
1668                  * entry. */
1669                 if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
1670                 {
1671                     if( xCheckRequiresARPResolution( pxNetworkBuffer ) == pdTRUE )
1672                     {
1673                         eReturn = eWaitingARPResolution;
1674                     }
1675                     else
1676                     {
1677                         /* IP address is not on the same subnet, ARP table can be updated.
1678                          * Refresh the ARP cache with the IP/MAC-address of the received
1679                          *  packet. For UDP packets, this will be done later in
1680                          *  xProcessReceivedUDPPacket(), as soon as it's know that the message
1681                          *  will be handled.  This will prevent the ARP cache getting
1682                          *  overwritten with the IP address of useless broadcast packets.
1683                          */
1684                         vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
1685                     }
1686                 }
1687 
1688                 if( eReturn != eWaitingARPResolution )
1689                 {
1690                     switch( ucProtocol )
1691                     {
1692                         case ipPROTOCOL_ICMP:
1693 
1694                             /* The IP packet contained an ICMP frame.  Don't bother checking
1695                              * the ICMP checksum, as if it is wrong then the wrong data will
1696                              * also be returned, and the source of the ping will know something
1697                              * went wrong because it will not be able to validate what it
1698                              * receives. */
1699                             #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
1700                                 {
1701                                     if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
1702                                     {
1703                                         eReturn = ProcessICMPPacket( pxNetworkBuffer );
1704                                     }
1705                                 }
1706                             #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
1707                             break;
1708 
1709                         case ipPROTOCOL_UDP:
1710                            {
1711                                /* The IP packet contained a UDP frame. */
1712 
1713                                /* Map the buffer onto a UDP-Packet struct to easily access the
1714                                 * fields of UDP packet. */
1715 
1716                                /* MISRA Ref 11.3.1 [Misaligned access] */
1717 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1718                                /* coverity[misra_c_2012_rule_11_3_violation] */
1719                                const UDPPacket_t * pxUDPPacket = ( ( const UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
1720                                uint16_t usLength;
1721                                BaseType_t xIsWaitingARPResolution = pdFALSE;
1722 
1723                                /* Note the header values required prior to the checksum
1724                                 * generation as the checksum pseudo header may clobber some of
1725                                 * these values. */
1726                                usLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength );
1727 
1728                                if( ( pxNetworkBuffer->xDataLength < sizeof( UDPPacket_t ) ) ||
1729                                    ( ( ( size_t ) usLength ) < sizeof( UDPHeader_t ) ) )
1730                                {
1731                                    eReturn = eReleaseBuffer;
1732                                }
1733                                else if( usLength > ( FreeRTOS_ntohs( pxIPHeader->usLength ) - ipSIZE_OF_IPv4_HEADER ) )
1734                                {
1735                                    /* The UDP packet is bigger than the IP-payload. Something is wrong, drop the packet. */
1736                                    eReturn = eReleaseBuffer;
1737                                }
1738                                else
1739                                {
1740                                    size_t uxPayloadSize_1, uxPayloadSize_2;
1741 
1742                                    /* Ensure that downstream UDP packet handling has the lesser
1743                                     * of: the actual network buffer Ethernet frame length, or
1744                                     * the sender's UDP packet header payload length, minus the
1745                                     * size of the UDP header.
1746                                     *
1747                                     * The size of the UDP packet structure in this implementation
1748                                     * includes the size of the Ethernet header, the size of
1749                                     * the IP header, and the size of the UDP header. */
1750                                    uxPayloadSize_1 = pxNetworkBuffer->xDataLength - sizeof( UDPPacket_t );
1751                                    uxPayloadSize_2 = ( ( size_t ) usLength ) - sizeof( UDPHeader_t );
1752 
1753                                    if( uxPayloadSize_1 > uxPayloadSize_2 )
1754                                    {
1755                                        pxNetworkBuffer->xDataLength = uxPayloadSize_2 + sizeof( UDPPacket_t );
1756                                    }
1757 
1758                                    /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
1759                                    pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
1760                                    pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
1761 
1762                                    /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
1763                                     * In some cases, the upper-layer checksum has been calculated
1764                                     * by the NIC driver. */
1765 
1766                                    /* Pass the packet payload to the UDP sockets
1767                                     * implementation. */
1768                                    if( xProcessReceivedUDPPacket( pxNetworkBuffer,
1769                                                                   pxUDPPacket->xUDPHeader.usDestinationPort,
1770                                                                   &( xIsWaitingARPResolution ) ) == pdPASS )
1771                                    {
1772                                        eReturn = eFrameConsumed;
1773                                    }
1774                                    else
1775                                    {
1776                                        /* Is this packet to be set aside for ARP resolution. */
1777                                        if( xIsWaitingARPResolution == pdTRUE )
1778                                        {
1779                                            eReturn = eWaitingARPResolution;
1780                                        }
1781                                    }
1782                                }
1783                            }
1784                            break;
1785 
1786                             #if ipconfigUSE_TCP == 1
1787                                 case ipPROTOCOL_TCP:
1788 
1789                                     if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
1790                                     {
1791                                         eReturn = eFrameConsumed;
1792                                     }
1793 
1794                                     /* Setting this variable will cause xTCPTimerCheck()
1795                                      * to be called just before the IP-task blocks. */
1796                                     xProcessedTCPMessage++;
1797                                     break;
1798                             #endif /* if ipconfigUSE_TCP == 1 */
1799                         default:
1800                             /* Not a supported frame type. */
1801                             eReturn = eReleaseBuffer;
1802                             break;
1803                     }
1804                 }
1805             }
1806         }
1807     }
1808 
1809     return eReturn;
1810 }
1811 
1812 /*-----------------------------------------------------------*/
1813 
1814 #if ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 )
1815 
1816 /**
1817  * @brief Although the driver will take care of checksum calculations, the IP-task
1818  *        will still check if the length fields are OK.
1819  *
1820  * @param[in] pucEthernetBuffer: The Ethernet packet received.
1821  * @param[in] uxBufferLength: The total number of bytes received.
1822  *
1823  * @return pdPASS when the length fields in the packet OK, pdFAIL when the packet
1824  *         should be dropped.
1825  */
xCheckSizeFields(const uint8_t * const pucEthernetBuffer,size_t uxBufferLength)1826     static BaseType_t xCheckSizeFields( const uint8_t * const pucEthernetBuffer,
1827                                         size_t uxBufferLength )
1828     {
1829         size_t uxLength;
1830         const IPPacket_t * pxIPPacket;
1831         UBaseType_t uxIPHeaderLength;
1832         uint8_t ucProtocol;
1833         uint16_t usLength;
1834         uint16_t ucVersionHeaderLength;
1835         size_t uxMinimumLength;
1836         BaseType_t xResult = pdFAIL;
1837 
1838         DEBUG_DECLARE_TRACE_VARIABLE( BaseType_t, xLocation, 0 );
1839 
1840         do
1841         {
1842             /* Check for minimum packet size: Ethernet header and an IP-header, 34 bytes */
1843             if( uxBufferLength < sizeof( IPPacket_t ) )
1844             {
1845                 DEBUG_SET_TRACE_VARIABLE( xLocation, 1 );
1846                 break;
1847             }
1848 
1849             /* Map the buffer onto a IP-Packet struct to easily access the
1850              * fields of the IP packet. */
1851 
1852             /* MISRA Ref 11.3.1 [Misaligned access] */
1853             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1854             /* coverity[misra_c_2012_rule_11_3_violation] */
1855             pxIPPacket = ( ( const IPPacket_t * ) pucEthernetBuffer );
1856 
1857             ucVersionHeaderLength = pxIPPacket->xIPHeader.ucVersionHeaderLength;
1858 
1859             /* Test if the length of the IP-header is between 20 and 60 bytes,
1860              * and if the IP-version is 4. */
1861             if( ( ucVersionHeaderLength < ipIPV4_VERSION_HEADER_LENGTH_MIN ) ||
1862                 ( ucVersionHeaderLength > ipIPV4_VERSION_HEADER_LENGTH_MAX ) )
1863             {
1864                 DEBUG_SET_TRACE_VARIABLE( xLocation, 2 );
1865                 break;
1866             }
1867 
1868             ucVersionHeaderLength = ( ucVersionHeaderLength & ( uint8_t ) 0x0FU ) << 2;
1869             uxIPHeaderLength = ( UBaseType_t ) ucVersionHeaderLength;
1870 
1871             /* Check if the complete IP-header is transferred. */
1872             if( uxBufferLength < ( ipSIZE_OF_ETH_HEADER + uxIPHeaderLength ) )
1873             {
1874                 DEBUG_SET_TRACE_VARIABLE( xLocation, 3 );
1875                 break;
1876             }
1877 
1878             /* Check if the complete IP-header plus protocol data have been transferred: */
1879             usLength = pxIPPacket->xIPHeader.usLength;
1880             usLength = FreeRTOS_ntohs( usLength );
1881 
1882             if( uxBufferLength < ( size_t ) ( ipSIZE_OF_ETH_HEADER + ( size_t ) usLength ) )
1883             {
1884                 DEBUG_SET_TRACE_VARIABLE( xLocation, 4 );
1885                 break;
1886             }
1887 
1888             /* Identify the next protocol. */
1889             ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
1890 
1891             /* Switch on the Layer 3/4 protocol. */
1892             if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
1893             {
1894                 /* Expect at least a complete UDP header. */
1895                 uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER;
1896             }
1897             else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
1898             {
1899                 uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER;
1900             }
1901             else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
1902                      ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
1903             {
1904                 uxMinimumLength = uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER;
1905             }
1906             else
1907             {
1908                 /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
1909                 DEBUG_SET_TRACE_VARIABLE( xLocation, 5 );
1910                 break;
1911             }
1912 
1913             if( uxBufferLength < uxMinimumLength )
1914             {
1915                 DEBUG_SET_TRACE_VARIABLE( xLocation, 6 );
1916                 break;
1917             }
1918 
1919             uxLength = ( size_t ) usLength;
1920             uxLength -= ( ( uint16_t ) uxIPHeaderLength ); /* normally, minus 20. */
1921 
1922             if( ( uxLength < ( ( size_t ) sizeof( UDPHeader_t ) ) ) ||
1923                 ( uxLength > ( ( size_t ) ipconfigNETWORK_MTU - ( size_t ) uxIPHeaderLength ) ) )
1924             {
1925                 /* For incoming packets, the length is out of bound: either
1926                  * too short or too long. For outgoing packets, there is a
1927                  * serious problem with the format/length. */
1928                 DEBUG_SET_TRACE_VARIABLE( xLocation, 7 );
1929                 break;
1930             }
1931 
1932             xResult = pdPASS;
1933         } while( ipFALSE_BOOL );
1934 
1935         if( xResult != pdPASS )
1936         {
1937             /* NOP if ipconfigHAS_PRINTF != 1 */
1938             FreeRTOS_printf( ( "xCheckSizeFields: location %ld\n", xLocation ) );
1939         }
1940 
1941         return xResult;
1942     }
1943 #endif /* ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1 ) */
1944 /*-----------------------------------------------------------*/
1945 
1946 /* This function is used in other files, has external linkage e.g. in
1947  * FreeRTOS_DNS.c. Not to be made static. */
1948 
1949 /**
1950  * @brief Send the Ethernet frame after checking for some conditions.
1951  *
1952  * @param[in,out] pxNetworkBuffer: The network buffer which is to be sent.
1953  * @param[in] xReleaseAfterSend: Whether this network buffer is to be released or not.
1954  */
vReturnEthernetFrame(NetworkBufferDescriptor_t * pxNetworkBuffer,BaseType_t xReleaseAfterSend)1955 void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer,
1956                            BaseType_t xReleaseAfterSend )
1957 {
1958     EthernetHeader_t * pxEthernetHeader;
1959 /* memcpy() helper variables for MISRA Rule 21.15 compliance*/
1960     const void * pvCopySource;
1961     void * pvCopyDest;
1962 
1963     #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
1964         NetworkBufferDescriptor_t * pxNewBuffer;
1965     #endif
1966 
1967     #if ( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 )
1968         {
1969             if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
1970             {
1971                 BaseType_t xIndex;
1972 
1973                 FreeRTOS_printf( ( "vReturnEthernetFrame: length %u\n", ( unsigned ) pxNetworkBuffer->xDataLength ) );
1974 
1975                 for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
1976                 {
1977                     pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
1978                 }
1979 
1980                 pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
1981             }
1982         }
1983     #endif /* if( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 ) */
1984 
1985     #if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
1986         if( xReleaseAfterSend == pdFALSE )
1987         {
1988             pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength );
1989 
1990             if( pxNewBuffer != NULL )
1991             {
1992                 xReleaseAfterSend = pdTRUE;
1993                 /* Want no rounding up. */
1994                 pxNewBuffer->xDataLength = pxNetworkBuffer->xDataLength;
1995             }
1996 
1997             pxNetworkBuffer = pxNewBuffer;
1998         }
1999 
2000         if( pxNetworkBuffer != NULL )
2001     #endif /* if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) */
2002     {
2003         /* Map the Buffer to Ethernet Header struct for easy access to fields. */
2004 
2005         /* MISRA Ref 11.3.1 [Misaligned access] */
2006         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
2007         /* coverity[misra_c_2012_rule_11_3_violation] */
2008         pxEthernetHeader = ( ( EthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer );
2009 
2010         /*
2011          * Use helper variables for memcpy() to remain
2012          * compliant with MISRA Rule 21.15.  These should be
2013          * optimized away.
2014          */
2015         /* Swap source and destination MAC addresses. */
2016         pvCopySource = &pxEthernetHeader->xSourceAddress;
2017         pvCopyDest = &pxEthernetHeader->xDestinationAddress;
2018         ( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxEthernetHeader->xDestinationAddress ) );
2019 
2020         pvCopySource = ipLOCAL_MAC_ADDRESS;
2021         pvCopyDest = &pxEthernetHeader->xSourceAddress;
2022         ( void ) memcpy( pvCopyDest, pvCopySource, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
2023 
2024         /* Send! */
2025         iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer );
2026         ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
2027     }
2028 }
2029 /*-----------------------------------------------------------*/
2030 
2031 /**
2032  * @brief Returns the IP address of the NIC.
2033  *
2034  * @return The IP address of the NIC.
2035  */
FreeRTOS_GetIPAddress(void)2036 uint32_t FreeRTOS_GetIPAddress( void )
2037 {
2038     return *ipLOCAL_IP_ADDRESS_POINTER;
2039 }
2040 /*-----------------------------------------------------------*/
2041 
2042 /**
2043  * @brief Sets the IP address of the NIC.
2044  *
2045  * @param[in] ulIPAddress: IP address of the NIC to be set.
2046  */
FreeRTOS_SetIPAddress(uint32_t ulIPAddress)2047 void FreeRTOS_SetIPAddress( uint32_t ulIPAddress )
2048 {
2049     *ipLOCAL_IP_ADDRESS_POINTER = ulIPAddress;
2050 }
2051 /*-----------------------------------------------------------*/
2052 
2053 /**
2054  * @brief Get the gateway address of the subnet.
2055  *
2056  * @return The IP-address of the gateway, zero if a gateway is
2057  *         not used/defined.
2058  */
FreeRTOS_GetGatewayAddress(void)2059 uint32_t FreeRTOS_GetGatewayAddress( void )
2060 {
2061     return xNetworkAddressing.ulGatewayAddress;
2062 }
2063 /*-----------------------------------------------------------*/
2064 
2065 /**
2066  * @brief Get the DNS server address.
2067  *
2068  * @return The IP address of the DNS server.
2069  */
FreeRTOS_GetDNSServerAddress(void)2070 uint32_t FreeRTOS_GetDNSServerAddress( void )
2071 {
2072     return xNetworkAddressing.ulDNSServerAddress;
2073 }
2074 /*-----------------------------------------------------------*/
2075 
2076 /**
2077  * @brief Get the netmask for the subnet.
2078  *
2079  * @return The 32 bit netmask for the subnet.
2080  */
FreeRTOS_GetNetmask(void)2081 uint32_t FreeRTOS_GetNetmask( void )
2082 {
2083     return xNetworkAddressing.ulNetMask;
2084 }
2085 /*-----------------------------------------------------------*/
2086 
2087 /**
2088  * @brief Update the MAC address.
2089  *
2090  * @param[in] ucMACAddress: the MAC address to be set.
2091  */
FreeRTOS_UpdateMACAddress(const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES])2092 void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] )
2093 {
2094     /* Copy the MAC address at the start of the default packet header fragment. */
2095     ( void ) memcpy( ipLOCAL_MAC_ADDRESS, ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
2096 }
2097 /*-----------------------------------------------------------*/
2098 
2099 /**
2100  * @brief Get the MAC address.
2101  *
2102  * @return The pointer to MAC address.
2103  */
FreeRTOS_GetMACAddress(void)2104 const uint8_t * FreeRTOS_GetMACAddress( void )
2105 {
2106     return ipLOCAL_MAC_ADDRESS;
2107 }
2108 /*-----------------------------------------------------------*/
2109 
2110 /**
2111  * @brief Set the netmask for the subnet.
2112  *
2113  * @param[in] ulNetmask: The 32 bit netmask of the subnet.
2114  */
FreeRTOS_SetNetmask(uint32_t ulNetmask)2115 void FreeRTOS_SetNetmask( uint32_t ulNetmask )
2116 {
2117     xNetworkAddressing.ulNetMask = ulNetmask;
2118 }
2119 /*-----------------------------------------------------------*/
2120 
2121 /**
2122  * @brief Set the gateway address.
2123  *
2124  * @param[in] ulGatewayAddress: The gateway address.
2125  */
FreeRTOS_SetGatewayAddress(uint32_t ulGatewayAddress)2126 void FreeRTOS_SetGatewayAddress( uint32_t ulGatewayAddress )
2127 {
2128     xNetworkAddressing.ulGatewayAddress = ulGatewayAddress;
2129 }
2130 /*-----------------------------------------------------------*/
2131 
2132 /**
2133  * @brief Returns whether the IP task is ready.
2134  *
2135  * @return pdTRUE if IP task is ready, else pdFALSE.
2136  */
xIPIsNetworkTaskReady(void)2137 BaseType_t xIPIsNetworkTaskReady( void )
2138 {
2139     return xIPTaskInitialised;
2140 }
2141 /*-----------------------------------------------------------*/
2142 
2143 /**
2144  * @brief Returns whether this node is connected to network or not.
2145  *
2146  * @return pdTRUE if network is connected, else pdFALSE.
2147  */
FreeRTOS_IsNetworkUp(void)2148 BaseType_t FreeRTOS_IsNetworkUp( void )
2149 {
2150     return xNetworkUp;
2151 }
2152 /*-----------------------------------------------------------*/
2153 
2154 #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
2155 
2156 /**
2157  * @brief Get the minimum space in the IP task queue.
2158  *
2159  * @return The minimum possible space in the IP task queue.
2160  */
uxGetMinimumIPQueueSpace(void)2161     UBaseType_t uxGetMinimumIPQueueSpace( void )
2162     {
2163         return uxQueueMinimumSpace;
2164     }
2165 #endif
2166 /*-----------------------------------------------------------*/
2167 
2168 /* Provide access to private members for verification. */
2169 #ifdef FREERTOS_TCP_ENABLE_VERIFICATION
2170     #include "aws_freertos_ip_verification_access_ip_define.h"
2171 #endif
2172