xref: /FreeRTOS-Plus-TCP-v4.0.0/source/FreeRTOS_Routing.c (revision 574b646147a48c508a8bfc82181fd89ea89c8c17)
1 /*
2  * FreeRTOS+TCP V2.3.1
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://aws.amazon.com/freertos
23  * http://www.FreeRTOS.org
24  */
25 
26 /**
27  * @file FreeRTOS_Routing.c
28  * @brief Implements endpoint interfaces functions and utilities.
29  */
30 
31 /* Standard includes. */
32 #include <stdint.h>
33 #include <stdio.h>
34 
35 /* FreeRTOS includes. */
36 #include "FreeRTOS.h"
37 #include "task.h"
38 
39 /* FreeRTOS+TCP includes. */
40 #include "FreeRTOS_IP.h"
41 #include "FreeRTOS_Sockets.h"
42 #include "FreeRTOS_IP_Private.h"
43 #include "FreeRTOS_ARP.h"
44 #include "FreeRTOS_UDP_IP.h"
45 #include "FreeRTOS_DHCP.h"
46 #include "NetworkBufferManagement.h"
47 #if ( ipconfigUSE_LLMNR == 1 )
48     #include "FreeRTOS_DNS.h"
49 #endif /* ipconfigUSE_LLMNR */
50 #include "FreeRTOS_Routing.h"
51 
52 /** @brief A list of all network end-points.  Each element has a next pointer. */
53 struct xNetworkEndPoint * pxNetworkEndPoints = NULL;
54 
55 /** @brief A list of all network interfaces: */
56 struct xNetworkInterface * pxNetworkInterfaces = NULL;
57 
58 /*
59  * Add a new IP-address to a Network Interface.  The object pointed to by
60  * 'pxEndPoint' and the interface must continue to exist.
61  */
62 static NetworkEndPoint_t * FreeRTOS_AddEndPoint( NetworkInterface_t * pxInterface,
63                                                  NetworkEndPoint_t * pxEndPoint );
64 
65 /** @brief A util struct to list the IPv6 IP types, prefix and type bit mask */
66 struct xIPv6_Couple
67 {
68     IPv6_Type_t eType;   /**< IPv6 IP type enum */
69     uint16_t usMask;     /**< IPv6 IP type bit mask */
70     uint16_t usExpected; /**< IPv6 IP type prefix */
71 };
72 /*-----------------------------------------------------------*/
73 
74 
75 #if ( ipconfigUSE_IPv4 != 0 )
76 
77 /**
78  * @brief Configure and install a new IPv4 end-point.
79  *
80  * @param[in] pxNetworkInterface The interface to which it belongs.
81  * @param[in] pxEndPoint Space for the new end-point. This memory is dedicated for the
82  *                        end-point and should not be freed or get any other purpose.
83  * @param[in] ucIPAddress The IP-address.
84  * @param[in] ucNetMask The prefix which shall be used for this end-point.
85  * @param[in] ucGatewayAddress The IP-address of a device on the LAN which can serve as
86  *                              as a gateway to the Internet.
87  * @param[in] ucDNSServerAddress The IP-address of a DNS server.
88  * @param[in] ucMACAddress The MAC address of the end-point.
89  */
FreeRTOS_FillEndPoint(NetworkInterface_t * pxNetworkInterface,NetworkEndPoint_t * pxEndPoint,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])90     void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface,
91                                 NetworkEndPoint_t * pxEndPoint,
92                                 const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
93                                 const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
94                                 const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
95                                 const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
96                                 const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] )
97     {
98         uint32_t ulIPAddress;
99 
100         if( ( pxNetworkInterface == NULL ) || ( pxEndPoint == NULL ) )
101         {
102             /* Invalid input. */
103             FreeRTOS_printf( ( "FreeRTOS_FillEndPoint: Invalid input, netif=%p, endpoint=%p\n",
104                                ( void * ) pxNetworkInterface,
105                                ( void * ) pxEndPoint ) );
106         }
107         else
108         {
109             /* Fill in and add an end-point to a network interface.
110              * The user must make sure that the object pointed to by 'pxEndPoint'
111              * will remain to exist. */
112             ( void ) memset( pxEndPoint, 0, sizeof( *pxEndPoint ) );
113 
114             ulIPAddress = FreeRTOS_inet_addr_quick( ucIPAddress[ 0 ], ucIPAddress[ 1 ], ucIPAddress[ 2 ], ucIPAddress[ 3 ] );
115             pxEndPoint->ipv4_settings.ulNetMask = FreeRTOS_inet_addr_quick( ucNetMask[ 0 ], ucNetMask[ 1 ], ucNetMask[ 2 ], ucNetMask[ 3 ] );
116             pxEndPoint->ipv4_settings.ulGatewayAddress = FreeRTOS_inet_addr_quick( ucGatewayAddress[ 0 ], ucGatewayAddress[ 1 ], ucGatewayAddress[ 2 ], ucGatewayAddress[ 3 ] );
117             pxEndPoint->ipv4_settings.ulDNSServerAddresses[ 0 ] = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );
118             pxEndPoint->ipv4_settings.ulBroadcastAddress = ulIPAddress | ~( pxEndPoint->ipv4_settings.ulNetMask );
119 
120             /* Copy the current values to the default values. */
121             ( void ) memcpy( &( pxEndPoint->ipv4_defaults ), &( pxEndPoint->ipv4_settings ), sizeof( pxEndPoint->ipv4_defaults ) );
122 
123             /* The default IP-address will be used in case DHCP is not used, or also if DHCP has failed, or
124              * when the user chooses to use the default IP-address. */
125             pxEndPoint->ipv4_defaults.ulIPAddress = ulIPAddress;
126 
127             /* The field 'ipv4_settings.ulIPAddress' will be set later on. */
128 
129             ( void ) memcpy( pxEndPoint->xMACAddress.ucBytes, ucMACAddress, sizeof( pxEndPoint->xMACAddress ) );
130             ( void ) FreeRTOS_AddEndPoint( pxNetworkInterface, pxEndPoint );
131         }
132     }
133 /*-----------------------------------------------------------*/
134 #endif /* ( ipconfigUSE_IPv4 != 0 ) */
135 
136 #if ( ipconfigCOMPATIBLE_WITH_SINGLE == 0 )
137 
138     #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
139         RoutingStats_t xRoutingStatistics;
140     #endif
141 
142 /*-----------------------------------------------------------*/
143 
144 /**
145  * @brief Add a network interface to the list of interfaces.  Check if the interface was
146  *        already added in an earlier call.
147  *
148  * @param[in] pxInterface The address of the new interface.
149  *
150  * @return The value of the parameter 'pxInterface'.
151  */
FreeRTOS_AddNetworkInterface(NetworkInterface_t * pxInterface)152     NetworkInterface_t * FreeRTOS_AddNetworkInterface( NetworkInterface_t * pxInterface )
153     {
154         NetworkInterface_t * pxIterator = NULL;
155 
156         if( pxInterface != NULL )
157         {
158             /* This interface will be added to the end of the list of interfaces, so
159              * there is no pxNext yet. */
160             pxInterface->pxNext = NULL;
161 
162             /* The end point for this interface has not yet been set. */
163             /*_RB_ As per other comments, why not set the end point at the same time? */
164             pxInterface->pxEndPoint = NULL;
165 
166             if( pxNetworkInterfaces == NULL )
167             {
168                 /* No other interfaces are set yet, so this is the first in the list. */
169                 pxNetworkInterfaces = pxInterface;
170             }
171             else
172             {
173                 /* Other interfaces are already defined, so iterate to the end of the
174                  * list. */
175 
176                 /*_RB_ Question - if ipconfigMULTI_INTERFACE is used to define the
177                  * maximum number of interfaces, would it be more efficient to have an
178                  * array of interfaces rather than a linked list of interfaces? */
179                 pxIterator = pxNetworkInterfaces;
180 
181                 for( ; ; )
182                 {
183                     if( pxIterator == pxInterface )
184                     {
185                         /* This interface was already added. */
186                         break;
187                     }
188 
189                     if( pxIterator->pxNext == NULL )
190                     {
191                         pxIterator->pxNext = pxInterface;
192                         break;
193                     }
194 
195                     pxIterator = pxIterator->pxNext;
196                 }
197             }
198         }
199 
200         return pxInterface;
201     }
202 /*-----------------------------------------------------------*/
203 
204 /**
205  * @brief Get the first Network Interface, or NULL if none has been added.
206  *
207  * @return The first interface, or NULL if none has been added
208  */
FreeRTOS_FirstNetworkInterface(void)209     NetworkInterface_t * FreeRTOS_FirstNetworkInterface( void )
210     {
211         return pxNetworkInterfaces;
212     }
213 /*-----------------------------------------------------------*/
214 
215 /**
216  * @brief Get the next interface.
217  *
218  * @return The interface that comes after 'pxInterface'. NULL when either 'pxInterface'
219  *         is NULL, or when 'pxInterface' is the last interface.
220  */
FreeRTOS_NextNetworkInterface(const NetworkInterface_t * pxInterface)221     NetworkInterface_t * FreeRTOS_NextNetworkInterface( const NetworkInterface_t * pxInterface )
222     {
223         NetworkInterface_t * pxReturn;
224 
225         if( pxInterface != NULL )
226         {
227             pxReturn = pxInterface->pxNext;
228         }
229         else
230         {
231             pxReturn = NULL;
232         }
233 
234         return pxReturn;
235     }
236 /*-----------------------------------------------------------*/
237 
238 /**
239  * @brief Add an end-point to a given interface.
240  *
241  * @param[in] pxInterface The interface that gets a new end-point.
242  * @param[in] pxEndPoint The end-point to be added.
243  *
244  * @return The value of the parameter 'pxEndPoint'.
245  */
FreeRTOS_AddEndPoint(NetworkInterface_t * pxInterface,NetworkEndPoint_t * pxEndPoint)246     static NetworkEndPoint_t * FreeRTOS_AddEndPoint( NetworkInterface_t * pxInterface,
247                                                      NetworkEndPoint_t * pxEndPoint )
248     {
249         NetworkEndPoint_t * pxIterator = NULL;
250 
251         /* This end point will go to the end of the list, so there is no pxNext
252          * yet. */
253         pxEndPoint->pxNext = NULL;
254 
255         /* Double link between the NetworkInterface_t that is using the addressing
256          * defined by this NetworkEndPoint_t structure. */
257         pxEndPoint->pxNetworkInterface = pxInterface;
258 
259         if( pxInterface->pxEndPoint == NULL )
260         {
261             /*_RB_ When would pxInterface->pxEndPoint ever not be NULL unless this is called twice? */
262             /*_HT_ It may be called twice. */
263             pxInterface->pxEndPoint = pxEndPoint;
264         }
265 
266         if( pxNetworkEndPoints == NULL )
267         {
268             /* No other end points are defined yet - so this is the first in the
269              * list. */
270             pxNetworkEndPoints = pxEndPoint;
271         }
272         else
273         {
274             /* Other end points are already defined so iterate to the end of the
275              * list. */
276             pxIterator = pxNetworkEndPoints;
277 
278             for( ; ; )
279             {
280                 if( pxIterator == pxEndPoint )
281                 {
282                     /* This end-point has already been added to the list. */
283                     break;
284                 }
285 
286                 if( pxIterator->pxNext == NULL )
287                 {
288                     pxIterator->pxNext = pxEndPoint;
289                     break;
290                 }
291 
292                 pxIterator = pxIterator->pxNext;
293             }
294         }
295 
296         #if ( ipconfigUSE_IPv6 != 0 )
297             if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED )
298             {
299                 FreeRTOS_printf( ( "FreeRTOS_AddEndPoint: MAC: %02x-%02x IPv6: %pip\n",
300                                    pxEndPoint->xMACAddress.ucBytes[ 4 ],
301                                    pxEndPoint->xMACAddress.ucBytes[ 5 ],
302                                    ( void * ) pxEndPoint->ipv6_defaults.xIPAddress.ucBytes ) );
303             }
304         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
305         #if ( ipconfigUSE_IPv4 != 0 )
306             if( pxEndPoint->bits.bIPv6 == pdFALSE_UNSIGNED )
307             {
308                 FreeRTOS_printf( ( "FreeRTOS_AddEndPoint: MAC: %02x-%02x IPv4: %xip\n",
309                                    pxEndPoint->xMACAddress.ucBytes[ 4 ],
310                                    pxEndPoint->xMACAddress.ucBytes[ 5 ],
311                                    ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_defaults.ulIPAddress ) ) );
312             }
313         #endif /* ( ipconfigUSE_IPv4 != 0 ) */
314 
315         return pxEndPoint;
316     }
317 /*-----------------------------------------------------------*/
318 
319 /**
320  * @brief Find the first end-point bound to a given interface.
321  *
322  * @param[in] pxInterface The interface whose first end-point will be returned.
323  *
324  * @return The first end-point that is found to the interface, or NULL when the
325  *         interface doesn't have any end-point yet.
326  */
FreeRTOS_FirstEndPoint(const NetworkInterface_t * pxInterface)327     NetworkEndPoint_t * FreeRTOS_FirstEndPoint( const NetworkInterface_t * pxInterface )
328     {
329         NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
330 
331         /* Find and return the NetworkEndPoint_t structure that is associated with
332          * the pxInterface NetworkInterface_t. *//*_RB_ Could this be made a two way link, so the NetworkEndPoint_t can just be read from the NetworkInterface_t structure?  Looks like there is a pointer in the struct already. */
333         while( pxEndPoint != NULL )
334         {
335             if( ( pxInterface == NULL ) || ( pxEndPoint->pxNetworkInterface == pxInterface ) )
336             {
337                 break;
338             }
339 
340             pxEndPoint = pxEndPoint->pxNext;
341         }
342 
343         return pxEndPoint;
344     }
345 /*-----------------------------------------------------------*/
346 
347 /**
348  * @brief Get the next end-point.  The parameter 'pxInterface' may be NULL, which means:
349  *        don't care which interface the end-point is bound to.
350  *
351  * @param[in] pxInterface An interface of interest, or NULL when iterating through all
352  *                         end-points.
353  * @param[in] pxEndPoint This is the current end-point.
354  *
355  * @return The end-point that is found, or NULL when there are no more end-points in the list.
356  */
FreeRTOS_NextEndPoint(const NetworkInterface_t * pxInterface,NetworkEndPoint_t * pxEndPoint)357     NetworkEndPoint_t * FreeRTOS_NextEndPoint( const NetworkInterface_t * pxInterface,
358                                                NetworkEndPoint_t * pxEndPoint )
359     {
360         NetworkEndPoint_t * pxResult = pxEndPoint;
361 
362         if( pxResult != NULL )
363         {
364             pxResult = pxResult->pxNext;
365 
366             while( pxResult != NULL )
367             {
368                 if( ( pxInterface == NULL ) || ( pxResult->pxNetworkInterface == pxInterface ) )
369                 {
370                     break;
371                 }
372 
373                 pxResult = pxResult->pxNext;
374             }
375         }
376         else
377         {
378             pxResult = FreeRTOS_FirstEndPoint( pxInterface );
379         }
380 
381         return pxResult;
382     }
383 /*-----------------------------------------------------------*/
384 
385 /**
386  * @brief Find the end-point which has a given IPv4 address.
387  *
388  * @param[in] ulIPAddress The IP-address of interest, or 0 if any IPv4 end-point may be returned.
389  * @param[in] ulWhere For maintaining routing statistics ulWhere acts as an index to the data structure
390  *                     that keep track of the number of times 'FreeRTOS_FindEndPointOnIP_IPv4()'
391  *                     has been called from a particular location. Used only if
392  *                     ipconfigHAS_ROUTING_STATISTICS is enabled.
393  *
394  * @return The end-point found or NULL.
395  */
FreeRTOS_FindEndPointOnIP_IPv4(uint32_t ulIPAddress,uint32_t ulWhere)396     NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv4( uint32_t ulIPAddress,
397                                                         uint32_t ulWhere )
398     {
399         NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
400 
401         #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
402             uint32_t ulLocationCount = ( uint32_t ) ( sizeof( xRoutingStatistics.ulLocationsIP ) / sizeof( xRoutingStatistics.ulLocationsIP[ 0 ] ) );
403 
404             xRoutingStatistics.ulOnIp++;
405 
406             if( ulWhere < ulLocationCount )
407             {
408                 xRoutingStatistics.ulLocationsIP[ ulWhere ]++;
409             }
410         #endif /* ( ipconfigHAS_ROUTING_STATISTICS == 1 ) */
411 
412         while( pxEndPoint != NULL )
413         {
414             #if ( ipconfigUSE_IPv4 != 0 )
415                 #if ( ipconfigUSE_IPv6 != 0 )
416                     if( pxEndPoint->bits.bIPv6 == 0U )
417                 #endif
418                 {
419                     if( ( ulIPAddress == 0U ) ||
420                         ( pxEndPoint->ipv4_settings.ulIPAddress == 0U ) ||
421                         ( pxEndPoint->ipv4_settings.ulIPAddress == ulIPAddress ) )
422                     {
423                         break;
424                     }
425                 }
426             #endif /* ( ipconfigUSE_IPv4 != 0 ) */
427 
428             pxEndPoint = pxEndPoint->pxNext;
429         }
430 
431         ( void ) ulIPAddress;
432 
433         return pxEndPoint;
434     }
435 /*-----------------------------------------------------------*/
436 
437     #if ( ipconfigUSE_IPv6 != 0 )
438 
439 /**
440  * @brief Find the end-point which handles a given IPv6 address.
441  *
442  * @param[in] pxIPAddress The IP-address of interest.
443  *
444  * @return The end-point found or NULL.
445  */
FreeRTOS_FindEndPointOnIP_IPv6(const IPv6_Address_t * pxIPAddress)446         NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv6( const IPv6_Address_t * pxIPAddress )
447         {
448             NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
449 
450             while( pxEndPoint != NULL )
451             {
452                 if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED )
453                 {
454                     if( xCompareIPv6_Address( &( pxEndPoint->ipv6_settings.xIPAddress ), pxIPAddress, pxEndPoint->ipv6_settings.uxPrefixLength ) == 0 )
455                     {
456                         break;
457                     }
458                 }
459 
460                 pxEndPoint = pxEndPoint->pxNext;
461             }
462 
463             return pxEndPoint;
464         }
465     #endif /* ipconfigUSE_IPv6 */
466 /*-----------------------------------------------------------*/
467 
468 /**
469  * @brief Find the end-point that has a certain MAC-address.
470  *
471  * @param[in] pxMACAddress The Ethernet packet.
472  * @param[in] pxInterface The interface on which the packet was received, or NULL when unknown.
473  *
474  * @return The end-point that has the given MAC-address.
475  */
FreeRTOS_FindEndPointOnMAC(const MACAddress_t * pxMACAddress,const NetworkInterface_t * pxInterface)476     NetworkEndPoint_t * FreeRTOS_FindEndPointOnMAC( const MACAddress_t * pxMACAddress,
477                                                     const NetworkInterface_t * pxInterface )
478     {
479         NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
480 
481         #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
482             {
483                 xRoutingStatistics.ulOnMAC++;
484             }
485         #endif
486 
487         /* If input MAC address is NULL, return NULL. */
488         if( pxMACAddress == NULL )
489         {
490             pxEndPoint = NULL;
491         }
492 
493         /*_RB_ Question - would it be more efficient to store the mac addresses in
494          * uin64_t variables for direct comparison instead of using memcmp()?  [don't
495          * know if there is a quick way of creating a 64-bit number from the 48-byte
496          * MAC address without getting junk in the top 2 bytes]. */
497 
498         /* Find the end-point with given MAC-address. */
499         while( pxEndPoint != NULL )
500         {
501             if( ( pxInterface == NULL ) || ( pxInterface == pxEndPoint->pxNetworkInterface ) )
502             {
503                 if( memcmp( pxEndPoint->xMACAddress.ucBytes, pxMACAddress->ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
504                 {
505                     break;
506                 }
507             }
508 
509             pxEndPoint = pxEndPoint->pxNext;
510         }
511 
512         return pxEndPoint;
513     }
514 /*-----------------------------------------------------------*/
515 
516 /**
517  * @brief Find an end-point that handles a given IPv4-address.
518  *
519  * @param[in] ulIPAddress The IP-address for which an end-point is looked-up.
520  * @param[in] ulWhere For maintaining routing statistics ulWhere acts as an index to the data structure
521  *                     that keep track of the number of times 'FreeRTOS_InterfaceEndPointOnNetMask()'
522  *                     has been called from a particular location. Used only if
523  *                     ipconfigHAS_ROUTING_STATISTICS is enabled.
524  *
525  * @return An end-point that has the same network mask as the given IP-address.
526  */
FreeRTOS_FindEndPointOnNetMask(uint32_t ulIPAddress,uint32_t ulWhere)527     NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask( uint32_t ulIPAddress,
528                                                         uint32_t ulWhere )
529     {
530         /* The 'ulWhere' parameter is only for debugging purposes. */
531         return FreeRTOS_InterfaceEndPointOnNetMask( NULL, ulIPAddress, ulWhere );
532     }
533 /*-----------------------------------------------------------*/
534 
535 /**
536  * @brief Find an end-point that handles a given IPv4-address.
537  *
538  * @param[in] pxInterface Only end-points that have this interface are returned, unless
539  *                         pxInterface is NULL.
540  * @param[in] ulIPAddress The IP-address for which an end-point is looked-up.
541  *
542  * @param[in] ulWhere For maintaining routing statistics ulWhere acts as an index to the data structure
543  *                     that keep track of the number of times 'FreeRTOS_InterfaceEndPointOnNetMask()'
544  *                     has been called from a particular location. Used only if
545  *                     ipconfigHAS_ROUTING_STATISTICS is enabled.
546  *
547  * @return An end-point that has the same network mask as the given IP-address.
548  */
FreeRTOS_InterfaceEndPointOnNetMask(const NetworkInterface_t * pxInterface,uint32_t ulIPAddress,uint32_t ulWhere)549     NetworkEndPoint_t * FreeRTOS_InterfaceEndPointOnNetMask( const NetworkInterface_t * pxInterface,
550                                                              uint32_t ulIPAddress,
551                                                              uint32_t ulWhere )
552     {
553         NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
554 
555         #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
556             uint32_t ulLocationCount = ( uint32_t ) ( sizeof( xRoutingStatistics.ulLocations ) / sizeof( xRoutingStatistics.ulLocations[ 0 ] ) );
557 
558             xRoutingStatistics.ulOnNetMask++;
559 
560             if( ulWhere < ulLocationCount )
561             {
562                 xRoutingStatistics.ulLocations[ ulWhere ]++;
563             }
564         #endif /* ( ipconfigHAS_ROUTING_STATISTICS == 1 ) */
565 
566         /* Find the best fitting end-point to reach a given IP-address. */
567 
568         /*_RB_ Presumably then a broadcast reply could go out on a different end point to that on
569          * which the broadcast was received - although that should not be an issue if the nodes are
570          * on the same LAN it could be an issue if the nodes are on separate LAN's. */
571 
572         while( pxEndPoint != NULL )
573         {
574             if( ( pxInterface == NULL ) || ( pxEndPoint->pxNetworkInterface == pxInterface ) )
575             {
576                 #if ( ipconfigUSE_IPv4 != 0 )
577                     #if ( ipconfigUSE_IPv6 != 0 )
578                         if( pxEndPoint->bits.bIPv6 == pdFALSE_UNSIGNED )
579                     #endif
580                     {
581                         if( ( ulIPAddress == ~0U ) ||
582                             ( ( ulIPAddress & pxEndPoint->ipv4_settings.ulNetMask ) == ( pxEndPoint->ipv4_settings.ulIPAddress & pxEndPoint->ipv4_settings.ulNetMask ) ) )
583                         {
584                             /* Found a match. */
585                             break;
586                         }
587                     }
588                 #endif /* if ( ipconfigUSE_IPv4 != 0 ) */
589             }
590 
591             pxEndPoint = pxEndPoint->pxNext;
592         }
593 
594         /* This was only for debugging. */
595         if( pxEndPoint == NULL )
596         {
597             FreeRTOS_debug_printf( ( "FreeRTOS_FindEndPointOnNetMask[%d]: No match for %xip\n",
598                                      ( unsigned ) ulWhere, ( unsigned ) FreeRTOS_ntohl( ulIPAddress ) ) );
599         }
600 
601         return pxEndPoint;
602     }
603 /*-----------------------------------------------------------*/
604 
605     #if ( ipconfigUSE_IPv6 != 0 )
606 
607 /**
608  * @brief Configure and install a new IPv6 end-point.
609  *
610  * @param[in] pxNetworkInterface The interface to which it belongs.
611  * @param[in] pxEndPoint Space for the new end-point. This memory is dedicated for the
612  *                        end-point and should not be freed or get any other purpose.
613  * @param[in] pxIPAddress The IP-address.
614  * @param[in] pxNetPrefix The prefix which shall be used for this end-point.
615  * @param[in] uxPrefixLength The length of the above end-point.
616  * @param[in] pxGatewayAddress The IP-address of a device on the LAN which can serve as
617  *                              as a gateway to the Internet.
618  * @param[in] pxDNSServerAddress The IP-address of a DNS server.
619  * @param[in] ucMACAddress The MAC address of the end-point.
620  */
FreeRTOS_FillEndPoint_IPv6(NetworkInterface_t * pxNetworkInterface,NetworkEndPoint_t * pxEndPoint,const IPv6_Address_t * pxIPAddress,const IPv6_Address_t * pxNetPrefix,size_t uxPrefixLength,const IPv6_Address_t * pxGatewayAddress,const IPv6_Address_t * pxDNSServerAddress,const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES])621         void FreeRTOS_FillEndPoint_IPv6( NetworkInterface_t * pxNetworkInterface,
622                                          NetworkEndPoint_t * pxEndPoint,
623                                          const IPv6_Address_t * pxIPAddress,
624                                          const IPv6_Address_t * pxNetPrefix,
625                                          size_t uxPrefixLength,
626                                          const IPv6_Address_t * pxGatewayAddress,
627                                          const IPv6_Address_t * pxDNSServerAddress,
628                                          const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] )
629         {
630             if( ( pxNetworkInterface == NULL ) ||
631                 ( pxEndPoint == NULL ) ||
632                 ( pxIPAddress == NULL ) ||
633                 ( ucMACAddress == NULL ) )
634             {
635                 /* Invalid input. */
636                 FreeRTOS_printf( ( "FreeRTOS_FillEndPoint_IPv6: Invalid input, netif=%p, endpoint=%p, pxIPAddress=%p, ucMACAddress=%p\n",
637                                    ( void * ) pxNetworkInterface,
638                                    ( void * ) pxEndPoint,
639                                    ( void * ) pxIPAddress,
640                                    ( void * ) ucMACAddress ) );
641             }
642             else
643             {
644                 ( void ) memset( pxEndPoint, 0, sizeof( *pxEndPoint ) );
645 
646                 pxEndPoint->bits.bIPv6 = pdTRUE_UNSIGNED;
647 
648                 pxEndPoint->ipv6_settings.uxPrefixLength = uxPrefixLength;
649 
650                 if( pxGatewayAddress != NULL )
651                 {
652                     ( void ) memcpy( pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, pxGatewayAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
653                 }
654 
655                 if( pxDNSServerAddress != NULL )
656                 {
657                     ( void ) memcpy( pxEndPoint->ipv6_settings.xDNSServerAddresses[ 0 ].ucBytes, pxDNSServerAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
658                 }
659 
660                 if( pxNetPrefix != NULL )
661                 {
662                     ( void ) memcpy( pxEndPoint->ipv6_settings.xPrefix.ucBytes, pxNetPrefix->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
663                 }
664 
665                 /* Copy the current values to the default values. */
666                 ( void ) memcpy( &( pxEndPoint->ipv6_defaults ), &( pxEndPoint->ipv6_settings ), sizeof( pxEndPoint->ipv6_defaults ) );
667 
668                 ( void ) memcpy( pxEndPoint->ipv6_defaults.xIPAddress.ucBytes, pxIPAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS );
669 
670                 ( void ) memcpy( pxEndPoint->xMACAddress.ucBytes, ucMACAddress, ipMAC_ADDRESS_LENGTH_BYTES );
671                 ( void ) FreeRTOS_AddEndPoint( pxNetworkInterface, pxEndPoint );
672             }
673         }
674     #endif /* if ( ipconfigUSE_IPv6 != 0 ) */
675 /*-----------------------------------------------------------*/
676 
677     #if ( ipconfigUSE_IPv6 != 0 )
678 
679 /**
680  * @brief Find an end-point that handles a given IPv6-address.
681  *
682  * @param[in] pxIPv6Address The IP-address for which an end-point is looked-up.
683  *
684  * @return An end-point that has the same network mask as the given IP-address.
685  */
FreeRTOS_FindEndPointOnNetMask_IPv6(const IPv6_Address_t * pxIPv6Address)686         NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask_IPv6( const IPv6_Address_t * pxIPv6Address )
687         {
688             NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
689 
690             while( pxEndPoint != NULL )
691             {
692                 if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED )
693                 {
694                     if( xCompareIPv6_Address( &( pxEndPoint->ipv6_settings.xIPAddress ), pxIPv6Address, pxEndPoint->ipv6_settings.uxPrefixLength ) == 0 )
695                     {
696                         break;
697                     }
698                 }
699 
700                 pxEndPoint = pxEndPoint->pxNext;
701             }
702 
703             return pxEndPoint;
704         }
705     #endif /* ipconfigUSE_IPv6 */
706 /*-----------------------------------------------------------*/
707 
708 /**
709  * @brief Check IP-type, IP- and MAC-address found in the network packet.
710  */
711     #define rMATCH_IP_ADDR      0   /**< Find an endpoint with a matching IP-address. */
712     #define rMATCH_IPv6_TYPE    1   /**< Find an endpoint with a matching IPv6 type (both global or non global). */
713     #define rMATCH_MAC_ADDR     2   /**< Find an endpoint with a matching MAC-address. */
714     #define rMATCH_IP_TYPE      3   /**< Find an endpoint with a matching IP-type, v4 or v6. */
715     #define rMATCH_COUNT        4   /**< The number of methods. */
716 
717     NetworkEndPoint_t * pxEasyFit( const NetworkInterface_t * pxNetworkInterface,
718                                    const uint16_t usFrameType,
719                                    const IP_Address_t * pxIPAddressFrom,
720                                    const IP_Address_t * pxIPAddressTo,
721                                    const MACAddress_t * pxMACAddress );
722 
723 /**
724  * @brief Find an end-point that handles an incoming packet based on its type, source/destination & MAC address.
725  *
726  * @param[in] pxNetworkInterface The interface via which the packet was received.
727  * @param[in] usFrameType Frame type of the packet.
728  * @param[in] pxIPAddressFrom Source IP address of the packet.
729  * @param[in] pxIPAddressTo Destination IP address of the packet.
730  * @param[in] pxMACAddress Destination MAC address of the packet.
731  *
732  * @return An end-point that handles the packet.
733  */
pxEasyFit(const NetworkInterface_t * pxNetworkInterface,const uint16_t usFrameType,const IP_Address_t * pxIPAddressFrom,const IP_Address_t * pxIPAddressTo,const MACAddress_t * pxMACAddress)734     NetworkEndPoint_t * pxEasyFit( const NetworkInterface_t * pxNetworkInterface,
735                                    const uint16_t usFrameType,
736                                    const IP_Address_t * pxIPAddressFrom,
737                                    const IP_Address_t * pxIPAddressTo,
738                                    const MACAddress_t * pxMACAddress )
739     {
740         NetworkEndPoint_t * pxEndPoint;
741         NetworkEndPoint_t * pxReturn = NULL;
742         /* endpoints found for IP-type, IP-address, and MAC-address. */
743         NetworkEndPoint_t * pxFound[ rMATCH_COUNT ] = { NULL, NULL, NULL, NULL };
744         BaseType_t xCount[ rMATCH_COUNT ] = { 0, 0, 0, 0 };
745         BaseType_t xIndex;
746         BaseType_t xIsIPv6 = ( usFrameType == ipIPv6_FRAME_TYPE ) ? pdTRUE : pdFALSE;
747         BaseType_t xGatewayTarget = pdFALSE;
748         BaseType_t xTargetGlobal = pdFALSE;
749 
750         ( void ) pxIPAddressFrom;
751         ( void ) xGatewayTarget;
752         ( void ) xTargetGlobal;
753 
754         #if ( ipconfigUSE_IPv6 != 0 )
755             if( xIsIPv6 == pdTRUE )
756             {
757                 /* Generic GW address fe80::1. */
758                 static const uint8_t ucBytes[ 16 ] =
759                 {
760                     0xfe, 0x80, 0x00, 0x00,
761                     0x00, 0x00, 0x00, 0x00,
762                     0x00, 0x00, 0x00, 0x00,
763                     0x00, 0x00, 0x00, 0x01
764                 };
765                 xGatewayTarget = ( memcmp( ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, 16 ) == 0 ) ? pdTRUE : pdFALSE;
766 
767                 if( xGatewayTarget == pdTRUE )
768                 {
769                     FreeRTOS_debug_printf( ( " GW address %pip to %pip\n",
770                                              ( void * ) pxIPAddressFrom->xIP_IPv6.ucBytes,
771                                              ( void * ) pxIPAddressTo->xIP_IPv6.ucBytes ) );
772                 }
773 
774                 xTargetGlobal = ( xIPv6_GetIPType( &( pxIPAddressTo->xIP_IPv6 ) ) == eIPv6_Global ) ? pdTRUE : pdFALSE;
775             }
776         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
777 
778         for( pxEndPoint = FreeRTOS_FirstEndPoint( pxNetworkInterface );
779              pxEndPoint != NULL;
780              pxEndPoint = FreeRTOS_NextEndPoint( pxNetworkInterface, pxEndPoint ) )
781         {
782             BaseType_t xSameMACAddress = ( memcmp( pxEndPoint->xMACAddress.ucBytes, pxMACAddress->ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) ? pdTRUE : pdFALSE;
783 
784             if( xIsIPv6 == ( BaseType_t ) pxEndPoint->bits.bIPv6 )
785             {
786                 pxFound[ rMATCH_IP_TYPE ] = pxEndPoint;
787                 xCount[ rMATCH_IP_TYPE ]++;
788 
789                 /* Case default is impossible to reach because no endpoints for disabled IP type. */
790                 switch( xIsIPv6 ) /* LCOV_EXCL_BR_LINE */
791                 {
792                     #if ( ipconfigUSE_IPv6 != 0 )
793                         case ( BaseType_t ) pdTRUE:
794                            {
795                                IPv6_Type_t xEndpointType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) );
796 
797                                if( xEndpointType != eIPv6_Unknown )
798                                {
799                                    BaseType_t xEndpointGlobal = ( xEndpointType == eIPv6_Global ) ? pdTRUE : pdFALSE;
800 
801                                    if( ( memcmp( pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) )
802                                    {
803                                        pxFound[ rMATCH_IP_ADDR ] = pxEndPoint;
804                                        xCount[ rMATCH_IP_ADDR ]++;
805                                    }
806                                    else if( xTargetGlobal == xEndpointGlobal )
807                                    {
808                                        pxFound[ rMATCH_IPv6_TYPE ] = pxEndPoint;
809                                        xCount[ rMATCH_IPv6_TYPE ]++;
810                                    }
811                                    else
812                                    {
813                                        /* do nothing, coverity happy */
814                                    }
815                                }
816                                else
817                                {
818                                    /* do nothing, coverity happy */
819                                }
820                            }
821                            break;
822                     #endif /* ( ipconfigUSE_IPv6 != 0 ) */
823 
824                     case ( BaseType_t ) pdFALSE:
825                     default:
826                         #if ( ipconfigUSE_IPv4 != 0 )
827                             if( pxEndPoint->ipv4_settings.ulIPAddress == pxIPAddressTo->ulIP_IPv4 )
828                             {
829                                 pxFound[ rMATCH_IP_ADDR ] = pxEndPoint;
830                                 xCount[ rMATCH_IP_ADDR ]++;
831                             }
832                             else
833                             {
834                                 /* do nothing, coverity happy */
835                             }
836                         #endif /* ( ipconfigUSE_IPv4 != 0 ) */
837 
838                         break;
839                 }
840 
841                 if( xSameMACAddress == pdTRUE )
842                 {
843                     xCount[ rMATCH_MAC_ADDR ]++;
844                     pxFound[ rMATCH_MAC_ADDR ] = pxEndPoint;
845                 }
846             }
847         }
848 
849         for( xIndex = 0; xIndex < rMATCH_COUNT; xIndex++ )
850         {
851             if( xCount[ xIndex ] >= 1 )
852             {
853                 pxReturn = pxFound[ xIndex ];
854                 break;
855             }
856         }
857 
858         #if ( ipconfigHAS_PRINTF != 0 )
859             if( pxReturn == NULL )
860             {
861                 char pcBufferFrom[ 40 ];
862                 char pcBufferTo[ 40 ];
863                 BaseType_t xFamily = ( usFrameType == ipIPv6_FRAME_TYPE ) ? FREERTOS_AF_INET6 : FREERTOS_AF_INET4;
864                 const char * xRetNtopTo;
865                 const char * xRetNtopFrom;
866                 xRetNtopTo = FreeRTOS_inet_ntop( xFamily,
867                                                  ( void * ) pxIPAddressTo->xIP_IPv6.ucBytes,
868                                                  pcBufferTo,
869                                                  sizeof( pcBufferTo ) );
870                 xRetNtopFrom = FreeRTOS_inet_ntop( xFamily,
871                                                    ( void * ) pxIPAddressFrom->xIP_IPv6.ucBytes,
872                                                    pcBufferFrom,
873                                                    sizeof( pcBufferFrom ) );
874 
875                 FreeRTOS_debug_printf( ( "EasyFit[%x]: %d %d %d ( %s ->%s ) BAD\n",
876                                          usFrameType,
877                                          ( unsigned ) xCount[ 0 ],
878                                          ( unsigned ) xCount[ 1 ],
879                                          ( unsigned ) xCount[ 2 ],
880                                          ( xRetNtopFrom == NULL ) ? "INVALID" : pcBufferFrom,
881                                          ( xRetNtopTo == NULL ) ? "INVALID" : pcBufferTo ) );
882             }
883         #endif /* ( ipconfigHAS_PRINTF != 0 ) */
884 
885         return pxReturn;
886     }
887 
888 /**
889  * @brief Find out the best matching end-point given an incoming Ethernet packet.
890  *
891  * @param[in] pxNetworkInterface The interface on which the packet was received.
892  * @param[in] pucEthernetBuffer The Ethernet packet that was just received.
893  *
894  * @return The end-point that should handle the incoming Ethernet packet.
895  */
FreeRTOS_MatchingEndpoint(const NetworkInterface_t * pxNetworkInterface,const uint8_t * pucEthernetBuffer)896     NetworkEndPoint_t * FreeRTOS_MatchingEndpoint( const NetworkInterface_t * pxNetworkInterface,
897                                                    const uint8_t * pucEthernetBuffer )
898     {
899         NetworkEndPoint_t * pxEndPoint = NULL;
900         /* MISRA Ref 11.3.1 [Misaligned access] */
901         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
902         /* coverity[misra_c_2012_rule_11_3_violation] */
903         const ProtocolPacket_t * pxPacket = ( ( const ProtocolPacket_t * ) pucEthernetBuffer );
904 
905         #if ( ipconfigUSE_IPv6 != 0 )
906             /* MISRA Ref 11.3.1 [Misaligned access] */
907             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
908             /* coverity[misra_c_2012_rule_11_3_violation] */
909             const IPPacket_IPv6_t * pxIPPacket_IPv6 = ( ( const IPPacket_IPv6_t * ) pucEthernetBuffer );
910         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
911 
912         configASSERT( pucEthernetBuffer != NULL );
913 
914         /* Check if 'pucEthernetBuffer()' has the expected alignment,
915          * which is 32-bits + 2. */
916         #ifndef _lint
917             {
918                 /* MISRA Ref 11.4.3 [Casting pointer to int for verification] */
919                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-114 */
920                 /* coverity[misra_c_2012_rule_11_4_violation] */
921                 uintptr_t uxAddress = ( uintptr_t ) pucEthernetBuffer;
922                 uxAddress += 2U;
923                 configASSERT( ( uxAddress % 4U ) == 0U );
924                 /* And in case configASSERT is not defined. */
925                 ( void ) uxAddress;
926             }
927         #endif /* ifndef _lint */
928 
929         /* An Ethernet packet has been received. Inspect the contents to see which
930          * defined end-point has the best match.
931          */
932 
933         #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
934             {
935                 /* Some stats while developing. */
936                 xRoutingStatistics.ulMatching++;
937             }
938         #endif
939         {
940             uint16_t usFrameType = pxPacket->xUDPPacket.xEthernetHeader.usFrameType;
941             IP_Address_t xIPAddressFrom;
942             IP_Address_t xIPAddressTo;
943             MACAddress_t xMACAddress;
944             BaseType_t xDoProcessPacket = pdFALSE;
945 
946             ( void ) memset( xIPAddressFrom.xIP_IPv6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS );
947             ( void ) memset( xIPAddressTo.xIP_IPv6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS );
948 
949             switch( usFrameType )
950             {
951                 case ipIPv6_FRAME_TYPE:
952 
953                     /* Handle IPv6 frame types if ipconfigUSE_IPv6 != 0 */
954                     #if ( ipconfigUSE_IPv6 != 0 )
955                         ( void ) memcpy( xIPAddressFrom.xIP_IPv6.ucBytes, pxIPPacket_IPv6->xIPHeader.xSourceAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
956                         ( void ) memcpy( xIPAddressTo.xIP_IPv6.ucBytes, pxIPPacket_IPv6->xIPHeader.xDestinationAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
957                         xDoProcessPacket = pdTRUE;
958                     #endif /* ( ipconfigUSE_IPv6 != 0 ) */
959 
960                     break;
961 
962                 case ipARP_FRAME_TYPE:
963 
964                     /* Handle ARP frame types if ipconfigUSE_IPv4 != 0 */
965                     #if ( ipconfigUSE_IPv4 != 0 )
966                         {
967                             /* MISRA Ref 11.3.1 [Misaligned access] */
968                             /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
969                             /* coverity[misra_c_2012_rule_11_3_violation] */
970                             const ARPPacket_t * pxARPFrame = ( const ARPPacket_t * ) pucEthernetBuffer;
971 
972                             if( pxARPFrame->xARPHeader.usOperation == ( uint16_t ) ipARP_REQUEST )
973                             {
974                                 ( void ) memcpy( xIPAddressFrom.xIP_IPv6.ucBytes, pxPacket->xARPPacket.xARPHeader.ucSenderProtocolAddress, sizeof( uint32_t ) );
975                                 xIPAddressTo.ulIP_IPv4 = pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress;
976                             }
977                             else if( pxARPFrame->xARPHeader.usOperation == ( uint16_t ) ipARP_REPLY )
978                             {
979                                 ( void ) memcpy( xIPAddressTo.xIP_IPv6.ucBytes, pxPacket->xARPPacket.xARPHeader.ucSenderProtocolAddress, sizeof( uint32_t ) );
980                                 xIPAddressFrom.ulIP_IPv4 = pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress;
981                             }
982                             else
983                             {
984                                 /* do nothing, coverity happy */
985                             }
986 
987                             FreeRTOS_debug_printf( ( "pxEasyFit: ARP %xip -> %xip\n", ( unsigned ) FreeRTOS_ntohl( xIPAddressFrom.ulIP_IPv4 ), ( unsigned ) FreeRTOS_ntohl( xIPAddressTo.ulIP_IPv4 ) ) );
988                         }
989                         xDoProcessPacket = pdTRUE;
990                     #endif /* ( ipconfigUSE_IPv4 != 0 ) */
991 
992                     break;
993 
994                 case ipIPv4_FRAME_TYPE:
995 
996                     /* Handle IPv4 frame types if ipconfigUSE_IPv4 != 0 */
997                     #if ( ipconfigUSE_IPv4 != 0 )
998                         xIPAddressFrom.ulIP_IPv4 = pxPacket->xUDPPacket.xIPHeader.ulSourceIPAddress;
999                         xIPAddressTo.ulIP_IPv4 = pxPacket->xUDPPacket.xIPHeader.ulDestinationIPAddress;
1000                         xDoProcessPacket = pdTRUE;
1001                     #endif /* ( ipconfigUSE_IPv4 != 0 ) */
1002 
1003                     break;
1004 
1005                 default:
1006                     #if ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES == 1 )
1007                         /* Custom frame types, match by MAC address only. */
1008                         xDoProcessPacket = pdTRUE;
1009                     #endif
1010 
1011                     break;
1012             }
1013 
1014             if( xDoProcessPacket == pdTRUE )
1015             {
1016                 ( void ) memcpy( xMACAddress.ucBytes, pxPacket->xUDPPacket.xEthernetHeader.xDestinationAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES );
1017                 pxEndPoint = pxEasyFit( pxNetworkInterface,
1018                                         usFrameType,
1019                                         &xIPAddressFrom,
1020                                         &xIPAddressTo,
1021                                         &xMACAddress );
1022             }
1023         }
1024         return pxEndPoint;
1025     }
1026 /*-----------------------------------------------------------*/
1027 
1028 /**
1029  * @brief Find an end-point that defines a gateway of a certain type ( IPv4 or IPv6 ).
1030  *
1031  * @param[in] xIPType The type of Gateway to look for ( ipTYPE_IPv4 or ipTYPE_IPv6 ).
1032  *
1033  * @return The end-point that will lead to the gateway, or NULL when no gateway was found.
1034  */
FreeRTOS_FindGateWay(BaseType_t xIPType)1035     NetworkEndPoint_t * FreeRTOS_FindGateWay( BaseType_t xIPType )
1036     {
1037         NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
1038 
1039         while( pxEndPoint != NULL )
1040         {
1041             #if ( ipconfigUSE_IPv6 == 0 )
1042                 ( void ) xIPType;
1043 
1044                 if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) /* access to ipv4_settings is checked. */
1045                 {
1046                     break;
1047                 }
1048             #else
1049                 if( ( xIPType == ( BaseType_t ) ipTYPE_IPv6 ) && ( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) )
1050                 {
1051                     /* Check if the IP-address is non-zero. */
1052                     if( memcmp( FreeRTOS_in6addr_any.ucBytes, pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 )
1053                     {
1054                         break;
1055                     }
1056                 }
1057                 else
1058                 if( ( xIPType == ( BaseType_t ) ipTYPE_IPv4 ) && ( pxEndPoint->bits.bIPv6 == pdFALSE_UNSIGNED ) )
1059                 {
1060                     if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U )
1061                     {
1062                         break;
1063                     }
1064                 }
1065                 else
1066                 {
1067                     /* This end-point is not the right IP-type. */
1068                 }
1069             #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1070             pxEndPoint = pxEndPoint->pxNext;
1071         }
1072 
1073         return pxEndPoint;
1074     }
1075 /*-----------------------------------------------------------*/
1076 
1077     #if ( ipconfigUSE_IPv6 != 0 )
1078 
1079 /* Get the first end-point belonging to a given interface.
1080  * When pxInterface is NULL, the very first end-point will be returned. */
1081 
1082 /**
1083  * @brief Find the first IPv6 end-point.
1084  *
1085  * @param[in] pxInterface Either NULL ( don't care ), or a specific interface.
1086  *
1087  * @return The end-point found, or NULL when there are no end-points at all.
1088  */
FreeRTOS_FirstEndPoint_IPv6(const NetworkInterface_t * pxInterface)1089         NetworkEndPoint_t * FreeRTOS_FirstEndPoint_IPv6( const NetworkInterface_t * pxInterface )
1090         {
1091             NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
1092 
1093             while( pxEndPoint != NULL )
1094             {
1095                 if( ( ( pxInterface == NULL ) || ( pxEndPoint->pxNetworkInterface == pxInterface ) ) && ( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) )
1096                 {
1097                     break;
1098                 }
1099 
1100                 pxEndPoint = pxEndPoint->pxNext;
1101             }
1102 
1103             return pxEndPoint;
1104         }
1105     #endif /* ipconfigUSE_IPv6 */
1106 /*-----------------------------------------------------------*/
1107 
1108 /**
1109  * @brief Get the end-point that is bound to a socket.
1110  *
1111  * @param[in] xSocket The socket of interest.
1112  *
1113  * @return An end-point or NULL in case the socket is not bound to an end-point.
1114  */
pxGetSocketEndpoint(ConstSocket_t xSocket)1115     NetworkEndPoint_t * pxGetSocketEndpoint( ConstSocket_t xSocket )
1116     {
1117         const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket;
1118         NetworkEndPoint_t * pxResult;
1119 
1120         if( pxSocket != NULL )
1121         {
1122             pxResult = pxSocket->pxEndPoint;
1123         }
1124         else
1125         {
1126             pxResult = NULL;
1127         }
1128 
1129         return pxResult;
1130     }
1131 /*-----------------------------------------------------------*/
1132 
1133 /**
1134  * @brief Assign an end-point to a socket.
1135  *
1136  * @param[in] xSocket The socket to which an end-point will be assigned.
1137  * @param[in] pxEndPoint The end-point to be assigned.
1138  */
vSetSocketEndpoint(Socket_t xSocket,NetworkEndPoint_t * pxEndPoint)1139     void vSetSocketEndpoint( Socket_t xSocket,
1140                              NetworkEndPoint_t * pxEndPoint )
1141     {
1142         FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
1143 
1144         if( pxSocket != NULL )
1145         {
1146             pxSocket->pxEndPoint = pxEndPoint;
1147         }
1148     }
1149 /*-----------------------------------------------------------*/
1150 
1151 #else /* ( ipconfigCOMPATIBLE_WITH_SINGLE == 0 ) */
1152 
1153 /* Here below the most important function of FreeRTOS_Routing.c in a short
1154  * version: it is assumed that only 1 interface and 1 end-point will be created.
1155  * The reason for this is downward compatibility with the earlier release of
1156  * FreeRTOS+TCP, which had a single network interface only. */
1157 
1158 /**
1159  * @brief Add a network interface to the list of interfaces.  Check if this will be
1160  *        first and only interface ( ipconfigCOMPATIBLE_WITH_SINGLE = 1 ).
1161  *
1162  * @param[in] pxInterface The address of the new interface.
1163  *
1164  * @return The value of the parameter 'pxInterface'.
1165  */
FreeRTOS_AddNetworkInterface(NetworkInterface_t * pxInterface)1166     NetworkInterface_t * FreeRTOS_AddNetworkInterface( NetworkInterface_t * pxInterface )
1167     {
1168         configASSERT( pxNetworkInterfaces == NULL );
1169         pxNetworkInterfaces = pxInterface;
1170         return pxInterface;
1171     }
1172 /*-----------------------------------------------------------*/
1173 
1174 /**
1175  * @brief And an end-point to an interface.  Note that when ipconfigCOMPATIBLE_WITH_SINGLE
1176  *        is defined, only one interface is allowed, which will have one end-point only.
1177  *
1178  * @param[in] pxInterface The interface to which the end-point is assigned.
1179  * @param[in] pxEndPoint The end-point to be assigned to the above interface.
1180  *
1181  * @return The value of the parameter 'pxEndPoint'.
1182  */
FreeRTOS_AddEndPoint(NetworkInterface_t * pxInterface,NetworkEndPoint_t * pxEndPoint)1183     static NetworkEndPoint_t * FreeRTOS_AddEndPoint( NetworkInterface_t * pxInterface,
1184                                                      NetworkEndPoint_t * pxEndPoint )
1185     {
1186         /* This code is in backward-compatibility mode.
1187          * Only one end-point is allowed, make sure that
1188          * no end-point has been defined yet. */
1189         configASSERT( pxNetworkEndPoints == NULL );
1190 
1191         /* This end point will go to the end of the list, so there is no pxNext
1192          * yet. */
1193         pxEndPoint->pxNext = NULL;
1194 
1195         /* Double link between the NetworkInterface_t that is using the addressing
1196          * defined by this NetworkEndPoint_t structure. */
1197         pxEndPoint->pxNetworkInterface = pxInterface;
1198 
1199         pxInterface->pxEndPoint = pxEndPoint;
1200 
1201         /* No other end points are defined yet - so this is the first in the
1202          * list. */
1203         pxNetworkEndPoints = pxEndPoint;
1204 
1205         return pxEndPoint;
1206     }
1207 /*-----------------------------------------------------------*/
1208 
1209 /**
1210  * @brief Find the end-point which has a given IPv4 address.
1211  *
1212  * @param[in] ulIPAddress The IP-address of interest, or 0 if any IPv4 end-point may be returned.
1213  *
1214  * @return The end-point found or NULL.
1215  */
FreeRTOS_FindEndPointOnIP_IPv4(uint32_t ulIPAddress,uint32_t ulWhere)1216     NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv4( uint32_t ulIPAddress,
1217                                                         uint32_t ulWhere )
1218     {
1219         NetworkEndPoint_t * pxResult = NULL;
1220 
1221         ( void ) ulIPAddress;
1222         ( void ) ulWhere;
1223 
1224         if( ( ulIPAddress == 0U ) || ( pxNetworkEndPoints->ipv4_settings.ulIPAddress == ulIPAddress ) )
1225         {
1226             pxResult = pxNetworkEndPoints;
1227         }
1228 
1229         return pxResult;
1230     }
1231 /*-----------------------------------------------------------*/
1232 
1233 /**
1234  * @brief Find the end-point that has a certain MAC-address.
1235  *
1236  * @param[in] pxMACAddress The Ethernet packet.
1237  * @param[in] pxInterface The interface on which the packet was received, or NULL when unknown.
1238  *
1239  * @return The end-point that has the given MAC-address.
1240  */
FreeRTOS_FindEndPointOnMAC(const MACAddress_t * pxMACAddress,const NetworkInterface_t * pxInterface)1241     NetworkEndPoint_t * FreeRTOS_FindEndPointOnMAC( const MACAddress_t * pxMACAddress,
1242                                                     const NetworkInterface_t * pxInterface )
1243     {
1244         NetworkEndPoint_t * pxResult = NULL;
1245 
1246         ( void ) pxMACAddress;
1247         ( void ) pxInterface;
1248 
1249         if( ( pxMACAddress != NULL ) && ( memcmp( pxNetworkEndPoints->xMACAddress.ucBytes, pxMACAddress->ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) )
1250         {
1251             pxResult = pxNetworkEndPoints;
1252         }
1253 
1254         return pxResult;
1255     }
1256 /*-----------------------------------------------------------*/
1257 
1258 /**
1259  * @brief Find an end-point that handles a given IPv4-address.
1260  *
1261  * @param[in] ulIPAddress The IP-address for which an end-point is looked-up.
1262  *
1263  * @return An end-point that has the same network mask as the given IP-address.
1264  */
FreeRTOS_FindEndPointOnNetMask(uint32_t ulIPAddress,uint32_t ulWhere)1265     NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask( uint32_t ulIPAddress,
1266                                                         uint32_t ulWhere )
1267     {
1268         return FreeRTOS_InterfaceEndPointOnNetMask( NULL, ulIPAddress, ulWhere );
1269     }
1270 /*-----------------------------------------------------------*/
1271 
1272 /**
1273  * @brief Find an end-point that defines a gateway of a certain type ( IPv4 or IPv6 ).
1274  *
1275  * @param[in] xIPType The type of Gateway to look for ( ipTYPE_IPv4 or ipTYPE_IPv6 ).
1276  *
1277  * @return The end-point that will lead to the gateway, or NULL when no gateway was found.
1278  */
FreeRTOS_FindGateWay(BaseType_t xIPType)1279     NetworkEndPoint_t * FreeRTOS_FindGateWay( BaseType_t xIPType )
1280     {
1281         NetworkEndPoint_t * pxReturn = NULL;
1282 
1283         ( void ) xIPType;
1284 
1285         if( pxNetworkEndPoints != NULL )
1286         {
1287             if( pxNetworkEndPoints->ipv4_settings.ulGatewayAddress != 0U )
1288             {
1289                 pxReturn = pxNetworkEndPoints;
1290             }
1291         }
1292 
1293         return pxReturn;
1294     }
1295 /*-----------------------------------------------------------*/
1296 
1297 /**
1298  * @brief Find the first end-point bound to a given interface.
1299  *
1300  * @param[in] pxInterface The interface whose first end-point will be returned.
1301  *
1302  * @return The first end-point that is found to the interface, or NULL when the
1303  *         interface doesn't have any end-point yet.
1304  */
FreeRTOS_FirstEndPoint(const NetworkInterface_t * pxInterface)1305     NetworkEndPoint_t * FreeRTOS_FirstEndPoint( const NetworkInterface_t * pxInterface )
1306     {
1307         ( void ) pxInterface;
1308 
1309         /* ipconfigCOMPATIBLE_WITH_SINGLE is defined and this is the simplified version:
1310          * only one interface and one end-point is defined. */
1311         return pxNetworkEndPoints;
1312     }
1313 /*-----------------------------------------------------------*/
1314 
1315 /**
1316  * @brief Get the first Network Interface, or NULL if none has been added.
1317  *
1318  * @return The first interface, or NULL if none has been added
1319  */
FreeRTOS_FirstNetworkInterface(void)1320     NetworkInterface_t * FreeRTOS_FirstNetworkInterface( void )
1321     {
1322         /* ipconfigCOMPATIBLE_WITH_SINGLE is defined: only one interface and
1323          * one end-point is defined. */
1324         return pxNetworkInterfaces;
1325     }
1326 /*-----------------------------------------------------------*/
1327 
1328 /**
1329  * @brief Find an end-point that handles a given IPv4-address.
1330  *
1331  * @param[in] pxInterface Ignored in this simplified version.
1332  * @param[in] ulIPAddress The IP-address for which an end-point is looked-up.
1333  *
1334  * @return An end-point that has the same network mask as the given IP-address.
1335  */
FreeRTOS_InterfaceEndPointOnNetMask(const NetworkInterface_t * pxInterface,uint32_t ulIPAddress,uint32_t ulWhere)1336     NetworkEndPoint_t * FreeRTOS_InterfaceEndPointOnNetMask( const NetworkInterface_t * pxInterface,
1337                                                              uint32_t ulIPAddress,
1338                                                              uint32_t ulWhere )
1339     {
1340         NetworkEndPoint_t * pxResult = NULL;
1341 
1342         ( void ) pxInterface;
1343         ( void ) ulWhere;
1344 
1345         if( ( ( ulIPAddress ^ pxNetworkEndPoints->ipv4_settings.ulIPAddress ) & pxNetworkEndPoints->ipv4_settings.ulNetMask ) == 0U )
1346         {
1347             pxResult = pxNetworkEndPoints;
1348         }
1349 
1350         return pxResult;
1351     }
1352 /*-----------------------------------------------------------*/
1353 
1354 /**
1355  * @brief Find out the best matching end-point given an incoming Ethernet packet.
1356  *
1357  * @param[in] pxNetworkInterface The interface on which the packet was received.
1358  * @param[in] pucEthernetBuffer The Ethernet packet that was just received.
1359  *
1360  * @return The end-point that should handle the incoming Ethernet packet.
1361  */
FreeRTOS_MatchingEndpoint(const NetworkInterface_t * pxNetworkInterface,const uint8_t * pucEthernetBuffer)1362     NetworkEndPoint_t * FreeRTOS_MatchingEndpoint( const NetworkInterface_t * pxNetworkInterface,
1363                                                    const uint8_t * pucEthernetBuffer )
1364     {
1365         ( void ) pxNetworkInterface;
1366         ( void ) pucEthernetBuffer;
1367 
1368         /* ipconfigCOMPATIBLE_WITH_SINGLE is defined: only one interface and
1369          * one end-point is defined. */
1370         return pxNetworkEndPoints;
1371     }
1372 /*-----------------------------------------------------------*/
1373 
1374 /**
1375  * @brief Get the next end-point.  As this is the simplified version, it will always
1376  *        return NULL.
1377  *
1378  * @param[in] pxInterface An interface of interest, or NULL when iterating through all
1379  *                         end-points.
1380  * @param[in] pxEndPoint This is the current end-point.
1381  *
1382  * @return NULL because ipconfigCOMPATIBLE_WITH_SINGLE is defined.
1383  */
FreeRTOS_NextEndPoint(const NetworkInterface_t * pxInterface,NetworkEndPoint_t * pxEndPoint)1384     NetworkEndPoint_t * FreeRTOS_NextEndPoint( const NetworkInterface_t * pxInterface,
1385                                                NetworkEndPoint_t * pxEndPoint )
1386     {
1387         ( void ) pxInterface;
1388         ( void ) pxEndPoint;
1389 
1390         return NULL;
1391     }
1392 /*-----------------------------------------------------------*/
1393 
1394 /**
1395  * @brief Get the next interface.
1396  *
1397  * @return NULL because ipconfigCOMPATIBLE_WITH_SINGLE is defined.
1398  */
FreeRTOS_NextNetworkInterface(const NetworkInterface_t * pxInterface)1399     NetworkInterface_t * FreeRTOS_NextNetworkInterface( const NetworkInterface_t * pxInterface )
1400     {
1401         ( void ) pxInterface;
1402 
1403         return NULL;
1404     }
1405 /*-----------------------------------------------------------*/
1406 
1407     #if ( ipconfigUSE_IPv6 != 0 )
FreeRTOS_FindEndPointOnIP_IPv6(const IPv6_Address_t * pxIPAddress)1408         NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv6( const IPv6_Address_t * pxIPAddress )
1409         {
1410             ( void ) pxIPAddress;
1411             return pxNetworkEndPoints;
1412         }
1413     #endif
1414 /*-----------------------------------------------------------*/
1415 
1416     #if ( ipconfigUSE_IPv6 != 0 )
FreeRTOS_FindEndPointOnNetMask_IPv6(const IPv6_Address_t * pxIPv6Address)1417         NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask_IPv6( const IPv6_Address_t * pxIPv6Address )
1418         {
1419             ( void ) pxIPv6Address;
1420             return pxNetworkEndPoints;
1421         }
1422 
1423     #endif
1424 /*-----------------------------------------------------------*/
1425 
1426     #if ( ipconfigUSE_IPv6 != 0 )
FreeRTOS_FirstEndPoint_IPv6(const NetworkInterface_t * pxInterface)1427         NetworkEndPoint_t * FreeRTOS_FirstEndPoint_IPv6( const NetworkInterface_t * pxInterface )
1428         {
1429             ( void ) pxInterface;
1430             return pxNetworkEndPoints;
1431         }
1432 
1433     #endif
1434 /*-----------------------------------------------------------*/
1435 
1436 #endif /* ( ipconfigCOMPATIBLE_WITH_SINGLE == 0 ) */
1437 
1438 /**
1439  * @brief Returns the IP type of the given IPv6 address.
1440  *
1441  * @param[in] pxAddress The IPv6 address whose type needs to be returned.
1442  * @returns The IP type of the given address.
1443  */
xIPv6_GetIPType(const IPv6_Address_t * pxAddress)1444 IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress )
1445 {
1446     IPv6_Type_t eResult = eIPv6_Unknown;
1447     BaseType_t xIndex;
1448     static const struct xIPv6_Couple xIPCouples[] =
1449     {
1450         /*    IP-type          Mask     Value */
1451         { eIPv6_Global,    0xE000U, 0x2000U }, /* 001 */
1452         { eIPv6_LinkLocal, 0xFFC0U, 0xFE80U }, /* 1111 1110 10 */
1453         { eIPv6_SiteLocal, 0xFFC0U, 0xFEC0U }, /* 1111 1110 11 */
1454         { eIPv6_Multicast, 0xFF00U, 0xFF00U }, /* 1111 1111 */
1455     };
1456 
1457     if( pxAddress != NULL )
1458     {
1459         for( xIndex = 0; xIndex < ARRAY_SIZE_X( xIPCouples ); xIndex++ )
1460         {
1461             uint16_t usAddress =
1462                 ( uint16_t ) ( ( ( ( uint16_t ) pxAddress->ucBytes[ 0 ] ) << 8 ) |
1463                                ( ( uint16_t ) pxAddress->ucBytes[ 1 ] ) );
1464 
1465             if( ( usAddress & xIPCouples[ xIndex ].usMask ) == xIPCouples[ xIndex ].usExpected )
1466             {
1467                 eResult = xIPCouples[ xIndex ].eType;
1468                 break;
1469             }
1470         }
1471     }
1472 
1473     return eResult;
1474 }
1475 /*-----------------------------------------------------------*/
1476 
1477 /**
1478  * @brief Returns the string representation of the IP address of the end point.
1479  *
1480  * @param[in] pxEndPoint End point for which IP address needs to be returned.
1481  * @param[in] pcBuffer A char buffer of required size to which the string will be written.
1482  * @param[in] uxSize Size of the char buffer - pcBuffer.
1483  *
1484  * @returns The pointer to the char buffer that contains the string representation of the end point IP address.
1485  *          The string will be "NULL" if the end point pointer is NULL.
1486  */
pcEndpointName(const NetworkEndPoint_t * pxEndPoint,char * pcBuffer,size_t uxSize)1487 const char * pcEndpointName( const NetworkEndPoint_t * pxEndPoint,
1488                              char * pcBuffer,
1489                              size_t uxSize )
1490 {
1491     if( pxEndPoint == NULL )
1492     {
1493         /* MISRA Ref 21.6.1 [snprintf and logging] */
1494         /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-216 */
1495         /* coverity[misra_c_2012_rule_21_6_violation] */
1496         ( void ) snprintf( pcBuffer, uxSize, "NULL" );
1497     }
1498     else
1499     {
1500         switch( pxEndPoint->bits.bIPv6 ) /* LCOV_EXCL_BR_LINE */
1501         {
1502             #if ( ipconfigUSE_IPv4 != 0 )
1503                 case pdFALSE_UNSIGNED:
1504                     ( void ) FreeRTOS_inet_ntop( FREERTOS_AF_INET4,
1505                                                  ( const void * ) &( pxEndPoint->ipv4_settings.ulIPAddress ),
1506                                                  pcBuffer,
1507                                                  ( socklen_t ) uxSize );
1508                     break;
1509             #endif /* ( ipconfigUSE_IPv4 != 0 ) */
1510 
1511             #if ( ipconfigUSE_IPv6 != 0 )
1512                 case pdTRUE_UNSIGNED:
1513                     ( void ) FreeRTOS_inet_ntop( FREERTOS_AF_INET6,
1514                                                  pxEndPoint->ipv6_settings.xIPAddress.ucBytes,
1515                                                  pcBuffer,
1516                                                  ( socklen_t ) uxSize );
1517                     break;
1518             #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1519 
1520             default:
1521                 /* MISRA 16.4 Compliance */
1522                 /* MISRA Ref 21.6.1 [snprintf and logging] */
1523                 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-216 */
1524                 /* coverity[misra_c_2012_rule_21_6_violation] */
1525                 ( void ) snprintf( pcBuffer, uxSize, "NULL" );
1526                 break;
1527         }
1528     }
1529 
1530     return pcBuffer;
1531 }
1532 /*-----------------------------------------------------------*/
1533