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