xref: /FreeRTOS-Plus-TCP-v4.0.0/tools/tcp_utilities/plus_tcp_demo_cli.c (revision 5757e07831d9be25a0ec85bbc9c5afe09fd90c81)
1 /*
2  * FreeRTOS+TCP <DEVELOPMENT BRANCH>
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * http://aws.amazon.com/freertos
25  * http://www.FreeRTOS.org
26  */
27 
28 /**
29  * @file plus_tcp_demo_cli.c
30  * @brief This module will handle a set of commands that help with integration testing.
31  *        It is used for integration tests, both IPv4 and IPv6.
32  */
33 
34 /* Standard includes. */
35 #include <stdio.h>
36 #include <time.h>
37 #include <ctype.h>
38 
39 /* FreeRTOS includes. */
40 #include <FreeRTOS.h>
41 #include "task.h"
42 #include "timers.h"
43 #include "queue.h"
44 #include "semphr.h"
45 #include "message_buffer.h"
46 
47 /* FreeRTOS+TCP includes. */
48 #include "FreeRTOS_IP.h"
49 #include "FreeRTOS_Sockets.h"
50 #include "FreeRTOS_DHCP.h"
51 #include "FreeRTOS_DNS.h"
52 #include "NetworkInterface.h"
53 #include "NetworkBufferManagement.h"
54 #include "FreeRTOS_ARP.h"
55 #include "FreeRTOS_IP_Private.h"
56 
57 #if ( ipconfigMULTI_INTERFACE != 0 )
58     #include "FreeRTOS_Routing.h"
59     #if ( ipconfigUSE_IPv6 != 0 )
60         #include "FreeRTOS_ND.h"
61     #endif
62 #endif
63 
64 #include "plus_tcp_demo_cli.h"
65 #include "http_client_test.h"
66 
67 #if ( ipconfigUSE_NTP_DEMO != 0 )
68     #include "NTPDemo.h"
69 #endif
70 
71 #if ( USE_IPERF != 0 )
72     #include "iperf_task.h"
73 #endif
74 
75 int verboseLevel;
76 
77 static uint32_t ulWorkCount, ulLastWorkCount;
78 
79 extern SemaphoreHandle_t xServerSemaphore;
80 
81 extern uint64_t ullGetHighResolutionTime( void );
82 
83 /* Some compilers do not support __attribute__( ( weak ) ) for a function declaration,
84  * hence updating the declaration.
85  */
86 #pragma WEAK ( ullGetHighResolutionTime )
ullGetHighResolutionTime(void)87 uint64_t ullGetHighResolutionTime( void )
88 {
89     /* In case you don't have a usec timer function. */
90     return xTaskGetTickCount();
91 }
92 
93 #define PING_TIMEOUT    100U
94 
95 typedef struct xCommandOptions
96 {
97     BaseType_t xDoClear;
98     BaseType_t xIPVersion; /* Zero means: do not change version, otherwise 4 or 6. */
99     BaseType_t xAsynchronous;
100     BaseType_t xLogging;
101 } CommandOptions_t;
102 
103 size_t uxGetOptions( CommandOptions_t * pxOptions,
104                      const char ** ppcCommand );
105 
106 int PING_COUNT_MAX = 10;
107 
108 static TaskHandle_t xServerWorkTaskHandle = NULL;
109 
110 extern void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
111                                        uint16_t usIdentifier );
112 #if ( ipconfigUSE_IPv6 != 0 )
113     static IPv6_Address_t xPing6IPAddress;
114     volatile BaseType_t xPing6Count = -1;
115 #endif
116 uint32_t ulPingIPAddress;
117 size_t uxPingSize = 32U;
118 volatile BaseType_t xPing4Count = -1;
119 volatile BaseType_t xPingReady;
120 static TickType_t uxPingTimes[ 2 ];
121 
122 static int pingLogging = pdFALSE;
123 
124 static void handle_udp( char * pcBuffer );
125 static void handle_arpq( char * pcBuffer );
126 static void handle_dnsq( char * pcBuffer );
127 static void handle_ping( char * pcBuffer );
128 #if ( ipconfigUSE_NTP_DEMO != 0 )
129     static void handle_ntp( char * pcBuffer );
130 #endif
131 static void handle_rand( char * pcBuffer );
132 static void handle_http( char * pcBuffer );
133 static void handle_whatismyipaddress( char * pcBuffer );
134 static void handle_ifconfig( char * pcBuffer );
135 static void handle_gw( char * pcBuffer );
136 static void handle_help( char * pcBuffer );
137 
138 void handle_user_test( char * pcBuffer );
139 
140 static void clear_caches( void );
141 
142 static volatile BaseType_t xDNSCount = 0;
143 
144 static struct freertos_addrinfo * pxDNSLookup( char * pcHost,
145                                                BaseType_t xIPVersion,
146                                                BaseType_t xAsynchronous,
147                                                BaseType_t xDoClear );
148 
149 static void vDNSEvent( const char * pcName,
150                        void * pvSearchID,
151                        struct freertos_addrinfo * pxAddrInfo );
152 
153 #if ( ipconfigMULTI_INTERFACE != 0 )
154     /* Defined in FreeRTOS_DNS.c */
155     void show_addressinfo( const struct freertos_addrinfo * pxAddress );
156 #endif
157 
158 /*-----------------------------------------------------------*/
159 
160 typedef void ( * pfhandler ) ( char * /*pcBuffer */ );
161 
162 struct xCommandCouple
163 {
164     char * pcCommand;
165     size_t uxCommandLength;
166     pfhandler pHandler;
167     const char * pcHelp;
168 };
169 
170 static struct xCommandCouple xCommands[] =
171 {
172     { "arpq",       4U,  handle_arpq,              "Lookup the MAC-address of an IPv4 or IPv6 address."         },
173     { "udp",        3U,  handle_udp,               "Send a text message to any UDP port."                       },
174     { "ping",       4U,  handle_ping,              "Look up a host and ping it 10 times."                       },
175     { "dnsq",       4U,  handle_dnsq,              "Look up a host using DNS, mDNS or LLMNR."                   },
176     { "rand",       4U,  handle_rand,              "Call the randomiser and print the resulting number.\n"      },
177     { "http",       4U,  handle_http,              "Connect to port 80 of a host and download \"index.html\"\n" },
178     { "user_test",  9U,  handle_user_test,         "A user-supplied function \"handle_user_test()\" is called." },
179     { "whatismyip", 10U, handle_whatismyipaddress, "Print my IP-address\n"                                      },
180     { "gw",         2U,  handle_gw,                "Show the configured gateway address\n"                      },
181     { "ifconfig",   8U,  handle_ifconfig,          "Show a few network parameters\n"                            },
182     { "help",       4U,  handle_help,              "Show this help\n"                                           },
183     #if ( ipconfigUSE_NTP_DEMO != 0 )
184         { "ntp",        3U,  handle_ntp,               "Contact an NTP server and ask the time.\n"                  },
185     #endif
186 };
187 
can_handle(char * pcBuffer,char * pcCommand,size_t uxLength,pfhandler phandler)188 static BaseType_t can_handle( char * pcBuffer,
189                               char * pcCommand,
190                               size_t uxLength,
191                               pfhandler phandler )
192 {
193     BaseType_t xReturn = pdFALSE;
194 
195     if( strncmp( pcBuffer, pcCommand, uxLength ) == 0 )
196     {
197         phandler( pcBuffer + uxLength );
198         xReturn = pdTRUE;
199     }
200 
201     return xReturn;
202 }
203 
204 /**
205  *
206  * @brief Create a task that runs the CLI.
207  * @return zero when the command was recognised and handled.
208  */
xHandleTestingCommand(char * pcBuffer,size_t uxBufferSize)209 BaseType_t xHandleTestingCommand( char * pcBuffer,
210                                   size_t uxBufferSize )
211 {
212     /* Becomes true if the command is handled. */
213     BaseType_t xReturn = pdFALSE;
214 
215     ( void ) uxBufferSize;
216 
217     if( ulLastWorkCount == ulWorkCount )
218     {
219         FreeRTOS_printf( ( "xHandleTestingCommand: the function xHandleTesting() was not called\n" ) );
220     }
221     else
222     {
223         ulLastWorkCount = ulWorkCount;
224     }
225 
226     if( xServerWorkTaskHandle == NULL )
227     {
228         xServerWorkTaskHandle = xTaskGetCurrentTaskHandle();
229     }
230 
231     if( strncmp( pcBuffer, "ver", 3 ) == 0 )
232     {
233         int level;
234 
235         if( sscanf( pcBuffer + 3, "%d", &level ) == 1 )
236         {
237             verboseLevel = level;
238         }
239 
240         FreeRTOS_printf( ( "Verbose level %d\n", verboseLevel ) );
241         xReturn = pdTRUE;
242     }
243     else
244     {
245         BaseType_t xIndex;
246 
247         for( xIndex = 0; xIndex < ARRAY_SIZE( xCommands ); xIndex++ )
248         {
249             struct xCommandCouple * pxCommand = &( xCommands[ xIndex ] );
250 
251             if( can_handle( pcBuffer, pxCommand->pcCommand, pxCommand->uxCommandLength, pxCommand->pHandler ) == pdTRUE )
252             {
253                 xReturn = pdTRUE;
254                 break;
255             }
256         }
257     }
258 
259     return xReturn;
260 }
261 /*-----------------------------------------------------------*/
262 
263 #if ( ipconfigMULTI_INTERFACE != 0 )
handle_ifconfig(char * pcBuffer)264     static void handle_ifconfig( char * pcBuffer )
265     {
266         NetworkInterface_t * pxInterface;
267         NetworkEndPoint_t * pxEndPoint;
268 
269         ( void ) pcBuffer;
270 
271         for( pxInterface = FreeRTOS_FirstNetworkInterface();
272              pxInterface != NULL;
273              pxInterface = FreeRTOS_NextNetworkInterface( pxInterface ) )
274         {
275             FreeRTOS_printf( ( "Interface %s\n", pxInterface->pcName ) );
276 
277             for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface );
278                  pxEndPoint != NULL;
279                  pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) )
280             {
281                 showEndPoint( pxEndPoint );
282             }
283         }
284     }
285 #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */
handle_ifconfig(char * pcBuffer)286     static void handle_ifconfig( char * pcBuffer )
287     {
288         ( void ) pcBuffer;
289         FreeRTOS_printf( ( "IP-address %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetIPAddress() ) ) );
290         FreeRTOS_printf( ( "Netmask    %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetNetmask() ) ) );
291         FreeRTOS_printf( ( "Gateway    %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetGatewayAddress() ) ) );
292         FreeRTOS_printf( ( "DNS        %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetDNSServerAddress() ) ) );
293     }
294 #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */
295 /*-----------------------------------------------------------*/
296 
pcARPReturnType(eARPLookupResult_t eResult)297 static const char * pcARPReturnType( eARPLookupResult_t eResult )
298 {
299     const char * pcReturn = "Unknown";
300 
301     switch( eResult )
302     {
303         case eARPCacheMiss:
304             pcReturn = "Miss";
305             break;
306 
307         case eARPCacheHit:
308             pcReturn = "Hit";
309             break;
310 
311         case eCantSendPacket:
312             pcReturn = "Can not send";
313             break;
314     }
315 
316     return pcReturn;
317 }
318 /*-----------------------------------------------------------*/
319 
320 #if ( ipconfigUSE_IPv6 != 0 )
pxFindEndpoint(IPv6_Address_t * pxAddress)321     static NetworkEndPoint_t * pxFindEndpoint( IPv6_Address_t * pxAddress )
322     {
323         NetworkEndPoint_t * pxEndpoint;
324 
325         for( pxEndpoint = FreeRTOS_FirstEndPoint( NULL );
326              pxEndpoint != NULL;
327              pxEndpoint = FreeRTOS_NextEndPoint( NULL, pxEndpoint ) )
328         {
329             if( memcmp( pxEndpoint->ipv6_settings.xGatewayAddress.ucBytes, pxAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 )
330             {
331                 break;
332             }
333         }
334 
335         return pxEndpoint;
336     }
337 /*-----------------------------------------------------------*/
338 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
339 
handle_udp(char * pcBuffer)340 static void handle_udp( char * pcBuffer )
341 {
342     /* e.g. "udp 192.168.2.11@1020 Hello world" */
343     CommandOptions_t xOptions;
344     char * ptr = pcBuffer;
345     char pcAtToken = '@';
346     char * pcToken = strchr( ptr, pcAtToken );
347     BaseType_t xIPType = 0;
348     IP_Address_t xAddress;
349 
350     uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
351 
352     if( xOptions.xDoClear )
353     {
354         clear_caches();
355         vNTPClearCache();
356     }
357 
358     if( pcToken != NULL )
359     {
360         BaseType_t rc;
361 
362         *pcToken = 0;
363 
364         rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, ptr, ( void * ) &xAddress );
365 
366         if( rc == pdPASS )
367         {
368             xIPType = ipTYPE_IPv4;
369         }
370         else
371         {
372             rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, ptr, ( void * ) &xAddress );
373 
374             if( rc == pdPASS )
375             {
376                 xIPType = ipTYPE_IPv6;
377             }
378         }
379 
380         *pcToken = pcAtToken;
381 
382         if( xIPType != 0 )
383         {
384             unsigned uPort;
385 
386             if( sscanf( pcToken + 1, "%u", &uPort ) >= 1 )
387             {
388                 BaseType_t uxFamily;
389 
390                 if( xIPType == ipTYPE_IPv6 )
391                 {
392                     uxFamily = FREERTOS_AF_INET6;
393                     FreeRTOS_printf( ( "Send packet to UDP %pip port %u\n", xAddress.xIP_IPv6.ucBytes, uPort ) );
394                 }
395                 else
396                 {
397                     uxFamily = FREERTOS_AF_INET;
398                     FreeRTOS_printf( ( "Send packet to UDP %xip port %u\n", ( unsigned ) FreeRTOS_ntohl( xAddress.ulIP_IPv4 ), uPort ) );
399                 }
400 
401                 static Socket_t xSocket = NULL;
402                 struct freertos_sockaddr xDestinationAddress;
403 
404                 if( xSocket == NULL )
405                 {
406                     struct freertos_sockaddr xSourceAddress;
407 
408                     memset( &xSourceAddress, 0, sizeof xSourceAddress );
409                     xSourceAddress.sin_family = uxFamily;
410                     xSourceAddress.sin_len = sizeof( xSourceAddress );
411                     xSourceAddress.sin_port = FreeRTOS_htons( uPort );
412                     xSocket = FreeRTOS_socket( uxFamily, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
413                     FreeRTOS_bind( xSocket, &xSourceAddress, sizeof xSourceAddress );
414                 }
415 
416                 if( xSocket != NULL )
417                 {
418                     size_t uxLength = strlen( pcBuffer );
419                     memset( &xDestinationAddress, 0, sizeof xDestinationAddress );
420 
421                     if( xIPType == ipTYPE_IPv6 )
422                     {
423                         memcpy( xDestinationAddress.sin_address.xIP_IPv6.ucBytes, xAddress.xIP_IPv6.ucBytes, 16 );
424                     }
425                     else
426                     {
427                         xDestinationAddress.sin_address.ulIP_IPv4 = xAddress.ulIP_IPv4;
428                     }
429 
430                     xDestinationAddress.sin_family = uxFamily;
431                     xDestinationAddress.sin_len = sizeof( xDestinationAddress );
432                     xDestinationAddress.sin_port = FreeRTOS_htons( uPort );
433                     char * pcCopy = ( char * ) pvPortMalloc( uxLength + 3 );
434 
435                     if( pcCopy != NULL )
436                     {
437                         memcpy( pcCopy, pcBuffer, uxLength );
438                         pcCopy[ uxLength + 0 ] = '\r';
439                         pcCopy[ uxLength + 1 ] = '\n';
440                         pcCopy[ uxLength + 2 ] = 0;
441                         rc = FreeRTOS_sendto( xSocket,
442                                               pcCopy,
443                                               uxLength + 2,
444                                               0,
445                                               &xDestinationAddress,
446                                               ( socklen_t ) sizeof( xDestinationAddress ) );
447                         vPortFree( pcCopy );
448                     }
449                     else
450                     {
451                         FreeRTOS_printf( ( "handle_udp: malloc failed\n" ) );
452                     }
453 
454                     vTaskDelay( pdMS_TO_TICKS( 500 ) );
455                 }
456             }
457         }
458     }
459 
460     if( ( pcToken == NULL ) || ( xIPType == 0 ) )
461     {
462         FreeRTOS_printf( ( "handle_udp: bad parameters: '%s'\n", pcBuffer ) );
463     }
464 }
465 /*-----------------------------------------------------------*/
466 
handle_arpq(char * pcBuffer)467 static void handle_arpq( char * pcBuffer )
468 {
469     CommandOptions_t xOptions;
470     char * ptr = pcBuffer;
471     eARPLookupResult_t eResult = eARPCacheMiss;
472     uint32_t ulIPAddress;
473     uint32_t ulLookUpIP;
474     MACAddress_t xMACAddress;
475     NetworkEndPoint_t * pxEndPoint = NULL;
476     BaseType_t xIPType = 0;
477     IP_Address_t xAddress;
478     IP_Address_t xLookupAddress;
479     BaseType_t rc;
480 
481     uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
482 
483     if( xOptions.xDoClear )
484     {
485         clear_caches();
486         vNTPClearCache();
487     }
488 
489     if( *ptr )
490     {
491         char * pcBegin = ptr;
492 
493         for( ; *ptr != 0; ptr++ )
494         {
495             if( !isxdigit( *ptr ) && ( *ptr != '.' ) && ( *ptr != ':' ) )
496             {
497                 *ptr = 0;
498                 break;
499             }
500         }
501 
502         memset( &xAddress, 0, sizeof xAddress );
503 
504         rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcBegin, ( void * ) &xAddress );
505 
506         if( rc == pdPASS )
507         {
508             xIPType = ipTYPE_IPv4;
509         }
510         else
511         {
512             rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcBegin, ( void * ) &xAddress );
513 
514             if( rc == pdPASS )
515             {
516                 xIPType = ipTYPE_IPv6;
517             }
518         }
519 
520         if( xIPType <= 0 )
521         {
522             FreeRTOS_printf( ( "handle_arpq: bad arguments: '%s'\n", pcBuffer ) );
523             return;
524         }
525 
526         ulIPAddress = xAddress.ulIP_IPv4;
527 
528         ulLookUpIP = ulIPAddress;
529         xLookupAddress = xAddress;
530 
531         switch( xIPType )
532         {
533             #if ( ipconfigUSE_IPv4 != 0 )
534                 case ipTYPE_IPv4:
535                     eResult = eARPGetCacheEntry( &ulLookUpIP, &xMACAddress, &pxEndPoint );
536                     FreeRTOS_printf( ( "ARPGetCacheEntry returns \"%s\" Look for %xip. Found end-point: %s\n",
537                                        pcARPReturnType( eResult ), ( unsigned ) FreeRTOS_htonl( ulLookUpIP ), ( pxEndPoint != NULL ) ? "yes" : "no" ) );
538                     break;
539             #endif /* ( ipconfigUSE_IPv4 != 0 ) */
540 
541             #if ( ipconfigUSE_IPv6 != 0 )
542                 case ipTYPE_IPv6:
543                     eResult = eNDGetCacheEntry( &( xLookupAddress.xIP_IPv6 ), &xMACAddress, &pxEndPoint );
544                     FreeRTOS_printf( ( "ARPGetCacheEntry returns \"%s\" Look for %pip. Found end-point: %s\n",
545                                        pcARPReturnType( eResult ), xAddress.xIP_IPv6.ucBytes, ( pxEndPoint != NULL ) ? "yes" : "no" ) );
546                     break;
547             #endif /* ( ipconfigUSE_IPv6 != 0 ) */
548 
549             default:
550                 /* MISRA 16.4 Compliance */
551                 FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) );
552                 break;
553         }
554 
555         if( ( eResult == eARPCacheMiss ) && ( pxEndPoint != NULL ) )
556         {
557             size_t uxNeededSize = sizeof( ARPPacket_t );
558 
559             if( xIPType == ipTYPE_IPv6 )
560             {
561                 uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPHeader_IPv6_t );
562             }
563 
564             NetworkBufferDescriptor_t * pxBuffer;
565 
566             switch( xIPType )
567             {
568                 #if ( ipconfigUSE_IPv4 != 0 )
569                     case ipTYPE_IPv4:
570                         FreeRTOS_printf( ( "handle_arpq: Looking up %xip\n",
571                                            ( unsigned ) FreeRTOS_ntohl( ulLookUpIP ) ) );
572 
573                         xARPWaitResolution( ulLookUpIP, 1000U );
574                         break;
575                 #endif /* ( ipconfigUSE_IPv4 != 0 ) */
576 
577                 #if ( ipconfigUSE_IPv6 != 0 )
578                     case ipTYPE_IPv6:
579                         pxBuffer = pxGetNetworkBufferWithDescriptor( BUFFER_FROM_WHERE_CALL( 180 ) uxNeededSize, pdMS_TO_TICKS( 100U ) );
580 
581                         if( pxBuffer != NULL )
582                         {
583                             UDPPacket_t * pxUDPPacket = ( ( UDPPacket_t * ) pxBuffer->pucEthernetBuffer );
584 
585                             /* 'ulLookUpIP' might be the IP-address of a gateway. */
586                             memcpy( pxBuffer->xIPAddress.xIP_IPv6.ucBytes, xLookupAddress.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
587                             pxUDPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE;
588                             pxBuffer->pxEndPoint = pxEndPoint;
589                             pxBuffer->pxInterface = pxBuffer->pxEndPoint->pxNetworkInterface;
590                             FreeRTOS_printf( ( "handle_arpq: Looking up %pip with%s end-point\n",
591                                                pxBuffer->xIPAddress.xIP_IPv6.ucBytes,
592                                                ( pxBuffer->pxEndPoint != NULL ) ? "" : "out" ) );
593 
594                             vNDSendNeighbourSolicitation( pxBuffer, &( pxBuffer->xIPAddress.xIP_IPv6 ) );
595                         }
596                         else
597                         {
598                             FreeRTOS_printf( ( "handle_arpq: pxGetNetworkBufferWithDescriptor failed\n" ) );
599                         }
600                         break;
601                 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
602 
603                 default:
604                     /* MISRA 16.4 Compliance */
605                     FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) );
606                     break;
607             }
608 
609             /* Let the IP-task do its work, and wait 500 ms. */
610             FreeRTOS_printf( ( "... Pause ...\n" ) );
611             vTaskDelay( pdMS_TO_TICKS( 500U ) );
612 
613             switch( xIPType )
614             {
615                 #if ( ipconfigUSE_IPv4 != 0 )
616                     case ipTYPE_IPv4:
617                         eResult = eARPGetCacheEntry( &ulLookUpIP, &xMACAddress, &pxEndPoint );
618                         break;
619                 #endif /* ( ipconfigUSE_IPv4 != 0 ) */
620 
621                 #if ( ipconfigUSE_IPv6 != 0 )
622                     case ipTYPE_IPv6:
623                         eResult = eNDGetCacheEntry( &( xLookupAddress.xIP_IPv6 ), &xMACAddress, &pxEndPoint );
624                         break;
625                 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
626 
627                 default:
628                     /* MISRA 16.4 Compliance */
629                     FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) );
630                     break;
631             }
632 
633             FreeRTOS_printf( ( "handle_arpq: after lookup: \"%s\"\n",
634                                pcARPReturnType( eResult ) ) );
635         }
636     }
637 }
638 /*-----------------------------------------------------------*/
639 
640 #if ( ipconfigMULTI_INTERFACE != 0 )
handle_dnsq(char * pcBuffer)641     static void handle_dnsq( char * pcBuffer )
642     {
643         CommandOptions_t xOptions;
644         char * ptr = pcBuffer;
645 
646         uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
647 
648         if( *ptr )
649         {
650             struct freertos_addrinfo * pxResult;
651 
652             pxResult = pxDNSLookup( ptr, xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xDoClear );
653 
654             if( pxResult != NULL )
655             {
656                 FreeRTOS_freeaddrinfo( pxResult );
657             }
658         }
659         else
660         {
661             FreeRTOS_printf( ( "Usage: dnsq <name>\n" ) );
662         }
663     }
664 /*-----------------------------------------------------------*/
665 #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */
666 
667 #if ( ( ipconfigMULTI_INTERFACE == 0 ) && ( ipconfigUSE_IPv4 != 0 ) )
668 
handle_dnsq(char * pcBuffer)669     static void handle_dnsq( char * pcBuffer )
670     {
671         CommandOptions_t xOptions;
672         char * ptr = pcBuffer;
673 
674         uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
675 
676         unsigned tmout = 4000;
677         static unsigned searchID;
678 
679         if( *ptr )
680         {
681             for( char * target = ptr; *target; target++ )
682             {
683                 if( isspace( *target ) )
684                 {
685                     *target = '\0';
686                     break;
687                 }
688             }
689 
690             if( xOptions.xDoClear )
691             {
692                 #if ( ipconfigUSE_DNS_CACHE != 0 )
693                     {
694                         FreeRTOS_dnsclear();
695                         FreeRTOS_printf( ( "Clear DNS cache and ARP\n" ) );
696                     }
697                 #endif /* ipconfigUSE_DNS_CACHE */
698                 #if ( ipconfigMULTI_INTERFACE != 0 )
699                     FreeRTOS_ClearARP( NULL );
700                 #else
701                     FreeRTOS_ClearARP();
702                 #endif
703                 FreeRTOS_printf( ( "Clear ARP cache\n" ) );
704             }
705 
706             FreeRTOS_printf( ( "DNS query: '%s'\n", ptr ) );
707             {
708                 uint32_t ulGatewayAddress;
709                 FreeRTOS_GetAddressConfiguration( NULL, NULL, &( ulGatewayAddress ), NULL );
710 
711                 if( xIsIPInARPCache( ulGatewayAddress ) == pdFALSE )
712                 {
713                     xARPWaitResolution( ulGatewayAddress, pdMS_TO_TICKS( 5000U ) );
714                 }
715             }
716             #if ( ipconfigDNS_USE_CALLBACKS != 0 )
717                 if( xOptions.xAsynchronous != 0 )
718                 {
719                     BaseType_t iCount;
720                     TickType_t uxWaitTime = 1000U;
721                     xDNSCount = 0;
722                     ip = FreeRTOS_gethostbyname_a( ptr, vDNSEvent, ( void * ) ++searchID, tmout );
723 
724                     for( iCount = 0; iCount < 10; iCount++ )
725                     {
726                         ulTaskNotifyTake( pdTRUE, uxWaitTime );
727 
728                         if( xDNSCount != 0 )
729                         {
730                             break;
731                         }
732                     }
733                 }
734                 else
735             #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */
736             {
737                 #if ( ipconfigDNS_USE_CALLBACKS == 0 )
738                     if( xOptions.xAsynchronous != 0 )
739                     {
740                         FreeRTOS_printf( ( "Asynchronous DNS requested but not installed.\n" ) );
741                     }
742                 #endif
743                 ip = FreeRTOS_gethostbyname( ptr );
744             }
745 
746             FreeRTOS_printf( ( "%s : %xip\n", ptr, ( unsigned ) FreeRTOS_ntohl( ip ) ) );
747             #if ( ipconfigUSE_DNS_CACHE == 0 )
748                 {
749                     FreeRTOS_printf( ( "DNS caching not enabled\n" ) );
750                 }
751             #else
752                 {
753                     uint32_t ulFirstIPAddress = 0U;
754                     BaseType_t xIndex;
755 
756                     for( xIndex = 0; xIndex < ( BaseType_t ) ipconfigDNS_CACHE_ENTRIES; xIndex++ )
757                     {
758                         /* Note: 'FreeRTOS_dnslookup' is only defined when
759                          * 'ipconfigUSE_DNS_CACHE' is enabled. */
760                         uint32_t ulThisIPAddress = FreeRTOS_dnslookup( ptr );
761 
762                         if( xIndex == 0 )
763                         {
764                             ulFirstIPAddress = ulThisIPAddress;
765                         }
766                         else if( ulFirstIPAddress == ulThisIPAddress )
767                         {
768                             break;
769                         }
770 
771                         FreeRTOS_printf( ( "Cache[%d]: %xip\n", ( int ) xIndex, ( unsigned ) FreeRTOS_ntohl( ulThisIPAddress ) ) );
772                     }
773                 }
774             #endif /* ( ipconfigUSE_DNS_CACHE == 0 ) */
775         }
776         else
777         {
778             FreeRTOS_printf( ( "Usage: dnsquery <name>\n" ) );
779         }
780     }
781 /*-----------------------------------------------------------*/
782 #endif /* ( ( ipconfigMULTI_INTERFACE == 0 ) && ( ipconfigUSE_IPv4 != 0 ) ) */
783 
handle_rand(char * pcBuffer)784 static void handle_rand( char * pcBuffer )
785 {
786     uint32_t ulNumber = 0x5a5a5a5a;
787     BaseType_t rc = xApplicationGetRandomNumber( &ulNumber );
788 
789     ( void ) pcBuffer;
790 
791     if( rc == pdPASS )
792     {
793         char buffer[ 33 ];
794         int index;
795         uint32_t ulMask = 0x80000000uL;
796 
797         for( index = 0; index < 32; index++ )
798         {
799             buffer[ index ] = ( ( ulNumber & ulMask ) != 0 ) ? '1' : '0';
800             ulMask >>= 1;
801         }
802 
803         buffer[ index ] = '\0';
804         FreeRTOS_printf( ( "Random %08lx (%s)\n", ulNumber, buffer ) );
805     }
806     else
807     {
808         FreeRTOS_printf( ( "Random failed\n" ) );
809     }
810 }
811 /*-----------------------------------------------------------*/
812 
uxGetOptions(CommandOptions_t * pxOptions,const char ** ppcCommand)813 size_t uxGetOptions( CommandOptions_t * pxOptions,
814                      const char ** ppcCommand )
815 {
816     size_t uxLength = 0U;
817     const char * pcCommand = *ppcCommand;
818 
819     memset( pxOptions, 0, sizeof( *pxOptions ) );
820     pxOptions->xIPVersion = 4;
821 
822     while( ( pcCommand[ uxLength ] != 0 ) && ( !isspace( ( uint8_t ) pcCommand[ uxLength ] ) ) )
823     {
824         switch( pcCommand[ uxLength ] )
825         {
826             case 'a':
827                 pxOptions->xAsynchronous = pdTRUE;
828                 break;
829 
830             case 'c':
831                 pxOptions->xDoClear = pdTRUE;
832                 break;
833 
834             case 'v':
835                 pxOptions->xLogging = pdTRUE;
836                 break;
837 
838             case '4':
839                 pxOptions->xIPVersion = 4;
840                 break;
841 
842             case '6':
843                 pxOptions->xIPVersion = 6;
844                 break;
845         }
846 
847         uxLength++;
848     }
849 
850     if( uxLength > 0U )
851     {
852         *ppcCommand = &( pcCommand[ uxLength ] );
853     }
854 
855     while( isspace( ( uint8_t ) ( *ppcCommand )[ 0 ] ) )
856     {
857         ( *ppcCommand )++;
858     }
859 
860     return uxLength;
861 }
862 
863 #if ( ipconfigUSE_NTP_DEMO != 0 )
handle_ntp(char * pcBuffer)864     static void handle_ntp( char * pcBuffer )
865     {
866         CommandOptions_t xOptions;
867         char * ptr = pcBuffer;
868 
869         uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
870 
871         if( xOptions.xDoClear )
872         {
873             clear_caches();
874             vNTPClearCache();
875         }
876 
877         vNTPSetNTPType( xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xLogging );
878         /* vStartNTPTask() may be called multiple times. */
879         vStartNTPTask( configMINIMAL_STACK_SIZE * 12, tskIDLE_PRIORITY + 1 );
880     }
881 #endif /* if ( ipconfigUSE_NTP_DEMO != 0 ) */
882 
883 #if ( ipconfigUSE_IPv6 != 0 )
handle_whatismyipaddress(char * pcBuffer)884     static void handle_whatismyipaddress( char * pcBuffer )
885     {
886         NetworkEndPoint_t * pxEndPoint;
887 
888         ( void ) pcBuffer;
889         FreeRTOS_printf( ( "Showing all end-points\n" ) );
890 
891         for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL );
892              pxEndPoint != NULL;
893              pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) )
894         {
895             #if ( ipconfigUSE_IPv6 != 0 )
896                 if( pxEndPoint->bits.bIPv6 )
897                 {
898                     FreeRTOS_printf( ( "IPv6: %pip on '%s'\n", pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxEndPoint->pxNetworkInterface->pcName ) );
899                 }
900                 else
901             #endif
902             {
903                 FreeRTOS_printf( ( "IPv4: %xip on '%s'\n", ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulIPAddress ), pxEndPoint->pxNetworkInterface->pcName ) );
904             }
905         }
906     }
907 #else /* if ( ipconfigUSE_IPv6 != 0 ) */
handle_whatismyipaddress(char * pcBuffer)908     static void handle_whatismyipaddress( char * pcBuffer )
909     {
910         ( void ) pcBuffer;
911         FreeRTOS_printf( ( "IPv4: %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetIPAddress() ) ) );
912     }
913 #endif /* if ( ipconfigUSE_IPv6 != 0 ) */
914 
handle_help(char * pcBuffer)915 static void handle_help( char * pcBuffer )
916 {
917     BaseType_t xIndex;
918 
919     ( void ) pcBuffer;
920     FreeRTOS_printf( ( "Available commands:\n" ) );
921 
922     for( xIndex = 0; xIndex < ARRAY_SIZE( xCommands ); xIndex++ )
923     {
924         FreeRTOS_printf( ( "%-11.11s: %s\n", xCommands[ xIndex ].pcCommand, xCommands[ xIndex ].pcHelp ) );
925     }
926 }
927 
928 #if ( ipconfigMULTI_INTERFACE != 0 )
handle_gw(char * pcBuffer)929     static void handle_gw( char * pcBuffer )
930     {
931         NetworkEndPoint_t * pxEndPoint;
932 
933         ( void ) pcBuffer;
934         FreeRTOS_printf( ( "Showing all gateways\n" ) );
935 
936         for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL );
937              pxEndPoint != NULL;
938              pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) )
939         {
940             #if ( ipconfigUSE_IPv6 != 0 )
941                 if( pxEndPoint->bits.bIPv6 )
942                 {
943                     if( memcmp( pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, FreeRTOS_in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 )
944                     {
945                         FreeRTOS_printf( ( "IPv6: %pip on '%s'\n", pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, pxEndPoint->pxNetworkInterface->pcName ) );
946                     }
947                 }
948                 else
949             #endif
950             {
951                 if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U )
952                 {
953                     FreeRTOS_printf( ( "IPv4: %xip on '%s'\n", ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulGatewayAddress ), pxEndPoint->pxNetworkInterface->pcName ) );
954                 }
955             }
956         }
957     }
958 #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */
handle_gw(char * pcBuffer)959     static void handle_gw( char * pcBuffer )
960     {
961         ( void ) pcBuffer;
962         FreeRTOS_printf( ( "Gateway: %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetGatewayAddress() ) ) );
963     }
964 #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */
965 
966 #if ( ipconfigMULTI_INTERFACE != 0 )
handle_ping(char * pcBuffer)967     static void handle_ping( char * pcBuffer )
968     {
969         struct freertos_addrinfo * pxDNSResult = NULL;
970         char * ptr = pcBuffer;
971         CommandOptions_t xOptions;
972         IP_Address_t xAddress;
973         BaseType_t xResult;
974 
975         uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
976 
977         pingLogging = xOptions.xLogging;
978 
979         char * pcHostname = ptr;
980 
981         if( *pcHostname == '\0' )
982         {
983             FreeRTOS_printf( ( "handle_ping: please provide a hostname of an IP-address\n" ) );
984             return;
985         }
986 
987         memset( &xAddress, 0, sizeof xAddress );
988 
989         xResult = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcHostname, ( void * ) &xAddress );
990 
991         if( xResult == pdPASS )
992         {
993             xOptions.xIPVersion = 4;
994         }
995         else
996         {
997             xResult = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcHostname, ( void * ) &xAddress );
998 
999             if( xResult == pdPASS )
1000             {
1001                 xOptions.xIPVersion = 6;
1002             }
1003         }
1004 
1005         if( xOptions.xIPVersion == 6 )
1006         {
1007             FreeRTOS_printf( ( "ping6: looking up name '%s' (%pip)\n", pcHostname, xAddress.xIP_IPv6.ucBytes ) );
1008         }
1009         else
1010         {
1011             FreeRTOS_printf( ( "ping4: looking up name '%s' (%xip)\n", pcHostname, ( unsigned ) FreeRTOS_ntohl( xAddress.ulIP_IPv4 ) ) );
1012         }
1013 
1014         if( xOptions.xDoClear )
1015         {
1016             clear_caches();
1017         }
1018 
1019         FreeRTOS_printf( ( "Calling pxDNSLookup\n" ) );
1020         pxDNSResult = pxDNSLookup( pcHostname, xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xDoClear );
1021 
1022         if( pxDNSResult != NULL )
1023         {
1024             switch( xOptions.xIPVersion )
1025             {
1026                 #if ( ipconfigUSE_IPv4 != 0 )
1027                     case 4:
1028                         FreeRTOS_printf( ( "ping4 to '%s' (%xip)\n", pcHostname, ( unsigned ) FreeRTOS_ntohl( pxDNSResult->ai_addr->sin_address.ulIP_IPv4 ) ) );
1029                         xPing4Count = 0;
1030                         #if ( ipconfigUSE_IPv6 != 0 )
1031                             xPing6Count = -1;
1032                         #endif
1033                         ulPingIPAddress = pxDNSResult->ai_addr->sin_address.ulIP_IPv4;
1034                         xARPWaitResolution( ulPingIPAddress, pdMS_TO_TICKS( 5000U ) );
1035                         FreeRTOS_SendPingRequest( ulPingIPAddress, uxPingSize, PING_TIMEOUT );
1036                         uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime();
1037                         break;
1038                 #endif /* ( ipconfigUSE_IPv4 != 0 ) */
1039 
1040                 #if ( ipconfigUSE_IPv6 != 0 )
1041                     case 6:
1042                         FreeRTOS_printf( ( "ping6 to '%s' (%pip)\n", pcHostname, pxDNSResult->ai_addr->sin_address.xIP_IPv6.ucBytes ) );
1043                         xPing4Count = -1;
1044                         xPing6Count = 0;
1045                         memcpy( xPing6IPAddress.ucBytes, pxDNSResult->ai_addr->sin_address.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
1046                         FreeRTOS_SendPingRequestIPv6( &xPing6IPAddress, uxPingSize, PING_TIMEOUT );
1047                         uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime();
1048                         break;
1049                 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1050 
1051                 default:
1052                     /* MISRA 16.4 Compliance */
1053                     FreeRTOS_debug_printf( ( "handle_ping: Undefined IP Type \n" ) );
1054                     break;
1055             }
1056         }
1057         else
1058         {
1059             FreeRTOS_printf( ( "ping -%d: '%s' not found\n", ( int ) xOptions.xIPVersion, ptr ) );
1060         }
1061     }
1062 /*-----------------------------------------------------------*/
1063 
1064 #else /* ipconfigMULTI_INTERFACE != 0 */
1065 
handle_ping(char * pcBuffer)1066     static void handle_ping( char * pcBuffer )
1067     {
1068         uint32_t ulIPAddress;
1069         char * ptr = pcBuffer;
1070 
1071         PING_COUNT_MAX = 10;
1072 
1073         CommandOptions_t xOptions;
1074 
1075         uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
1076 
1077         pingLogging = xOptions.xLogging;
1078 
1079         FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );
1080 
1081         if( *ptr != 0 )
1082         {
1083             char * rest = strchr( ptr, ' ' );
1084 
1085             if( rest )
1086             {
1087                 *( rest++ ) = '\0';
1088             }
1089 
1090             ulIPAddress = FreeRTOS_inet_addr( ptr );
1091 
1092             while( *ptr && !isspace( *ptr ) )
1093             {
1094                 ptr++;
1095             }
1096 
1097             unsigned count;
1098 
1099             if( ( rest != NULL ) && ( sscanf( rest, "%u", &count ) > 0 ) )
1100             {
1101                 PING_COUNT_MAX = count;
1102             }
1103         }
1104 
1105         FreeRTOS_printf( ( "ping to %xip\n", ( unsigned ) FreeRTOS_htonl( ulIPAddress ) ) );
1106 
1107         ulPingIPAddress = ulIPAddress;
1108         xPing4Count = 0;
1109         #if ( ipconfigUSE_IPv6 != 0 )
1110             xPing6Count = -1;
1111         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1112         xPingReady = pdFALSE;
1113 
1114         if( xOptions.xDoClear )
1115         {
1116             #if ( ipconfigMULTI_INTERFACE != 0 )
1117                 FreeRTOS_ClearARP( NULL );
1118             #else
1119                 FreeRTOS_ClearARP();
1120             #endif
1121             FreeRTOS_printf( ( "Clearing ARP cache\n" ) );
1122         }
1123 
1124         FreeRTOS_SendPingRequest( ulIPAddress, uxPingSize, PING_TIMEOUT );
1125         uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime();
1126     }
1127 #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */
1128 /*-----------------------------------------------------------*/
1129 
handle_http(char * pcBuffer)1130 static void handle_http( char * pcBuffer )
1131 {
1132     char * ptr = pcBuffer;
1133     CommandOptions_t xOptions;
1134 
1135     pingLogging = pdFALSE;
1136 
1137     uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) );
1138 
1139     if( xOptions.xIPVersion == 6 )
1140     {
1141         FreeRTOS_printf( ( "http IPv6\n" ) );
1142     }
1143 
1144     if( *ptr != 0 )
1145     {
1146         unsigned portNr = 80U;
1147         char * pcHost = ptr;
1148         char * pcFileName;
1149         char * next = ptr;
1150 
1151         while( ( *next != 0 ) && ( isspace( *next ) == 0 ) )
1152         {
1153             next++;
1154         }
1155 
1156         while( isspace( *next ) != 0 )
1157         {
1158             /* Erase the space. */
1159             *next = 0;
1160             next++;
1161         }
1162 
1163         pcFileName = next;
1164 
1165         while( ( *next != 0 ) && ( isspace( *next ) == 0 ) )
1166         {
1167             next++;
1168         }
1169 
1170         while( isspace( *next ) != 0 )
1171         {
1172             /* Erase the space. */
1173             *next = 0;
1174             next++;
1175         }
1176 
1177         if( isdigit( *next ) )
1178         {
1179             ( void ) sscanf( next, "%u", &portNr );
1180         }
1181 
1182         if( xOptions.xDoClear )
1183         {
1184             clear_caches();
1185         }
1186 
1187         {
1188             IP_Address_t xAddress;
1189             BaseType_t rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcHost, ( void * ) &xAddress );
1190 
1191             if( rc == pdPASS )
1192             {
1193                 xOptions.xIPVersion = 6;
1194             }
1195             else
1196             {
1197                 rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcHost, ( void * ) &xAddress );
1198 
1199                 if( rc == pdPASS )
1200                 {
1201                     xOptions.xIPVersion = 4;
1202                 }
1203             }
1204         }
1205 
1206         /* Get '192.168.2.11' from '/index.html' at port 33001 */
1207         FreeRTOS_printf( ( "Get '%s' from '%s' at port %u\n", pcFileName, pcHost, portNr ) );
1208         #if ( USE_ECHO_TASK != 0 )
1209             vStartHTTPClientTest( configMINIMAL_STACK_SIZE * 8, tskIDLE_PRIORITY + 1 );
1210             wakeupHTTPClient( 0U, pcHost, pcFileName, portNr, xOptions.xIPVersion );
1211         #else
1212             FreeRTOS_printf( ( "handle_http: please define 'USE_ECHO_TASK'\n" ) );
1213         #endif
1214     }
1215     else
1216     {
1217         FreeRTOS_printf( ( "Usage: http <hostname>\n" ) );
1218     }
1219 }
1220 /*-----------------------------------------------------------*/
1221 
vApplicationPingReplyHook(ePingReplyStatus_t eStatus,uint16_t usIdentifier)1222 void vApplicationPingReplyHook( ePingReplyStatus_t eStatus,
1223                                 uint16_t usIdentifier )
1224 {
1225     uxPingTimes[ 1 ] = ( TickType_t ) ullGetHighResolutionTime();
1226 
1227     if( ( xPing4Count >= 0 ) && ( xPing4Count < PING_COUNT_MAX ) )
1228     {
1229         xPing4Count++;
1230 
1231         if( pingLogging || ( xPing4Count == PING_COUNT_MAX ) )
1232         {
1233             FreeRTOS_printf( ( "Received reply %d: status %d ID %04x\n", ( int ) xPing4Count, ( int ) eStatus, usIdentifier ) );
1234         }
1235     }
1236 
1237     #if ( ipconfigUSE_IPv6 != 0 )
1238         if( ( xPing6Count >= 0 ) && ( xPing6Count < PING_COUNT_MAX ) )
1239         {
1240             xPing6Count++;
1241 
1242             if( pingLogging || ( xPing6Count == PING_COUNT_MAX ) )
1243             {
1244                 FreeRTOS_printf( ( "Received reply %d: status %d ID %04x\n", ( int ) xPing6Count, ( int ) eStatus, usIdentifier ) );
1245             }
1246         }
1247     #endif
1248     xPingReady = pdTRUE;
1249 
1250     if( xServerSemaphore != NULL )
1251     {
1252         xSemaphoreGive( xServerSemaphore );
1253     }
1254 }
1255 /*-----------------------------------------------------------*/
1256 
xHandleTesting()1257 void xHandleTesting()
1258 {
1259     /* A counter to check if the application calls this work function.
1260      * It should be called regularly from the application.
1261      * he application will block on 'xServerSemaphore'. */
1262     ulWorkCount++;
1263 
1264     if( xPingReady )
1265     {
1266         TickType_t uxTimeTicks = uxPingTimes[ 1 ] - uxPingTimes[ 0 ];
1267         #if ( ipconfigUSE_IPv6 != 0 )
1268             FreeRTOS_printf( ( "xPingReady %d xPing4 %d xPing6 %d  Delta %u\n",
1269                                ( int ) xPingReady, ( int ) xPing4Count, ( int ) xPing6Count, ( unsigned ) uxTimeTicks ) );
1270         #else
1271             FreeRTOS_printf( ( "xPingReady %d xPing4 %d  Delta %u\n", ( int ) xPingReady, ( int ) xPing4Count, ( unsigned ) uxTimeTicks ) );
1272         #endif
1273         xPingReady = pdFALSE;
1274 
1275         if( ( xPing4Count >= 0 ) && ( xPing4Count < PING_COUNT_MAX ) )
1276         {
1277             /* 10 bytes, 100 clock ticks. */
1278             FreeRTOS_SendPingRequest( ulPingIPAddress, uxPingSize, PING_TIMEOUT );
1279             uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime();
1280         }
1281 
1282         #if ( ipconfigUSE_IPv6 != 0 )
1283             if( ( xPing6Count >= 0 ) && ( xPing6Count < PING_COUNT_MAX ) )
1284             {
1285                 FreeRTOS_SendPingRequestIPv6( &xPing6IPAddress, uxPingSize, PING_TIMEOUT );
1286                 uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime();
1287             }
1288         #endif
1289     }
1290 }
1291 /*-----------------------------------------------------------*/
1292 
1293 #if ( ipconfigMULTI_INTERFACE != 0 )
pxDNSLookup(char * pcHost,BaseType_t xIPVersion,BaseType_t xAsynchronous,BaseType_t xDoClear)1294     static struct freertos_addrinfo * pxDNSLookup( char * pcHost,
1295                                                    BaseType_t xIPVersion,
1296                                                    BaseType_t xAsynchronous,
1297                                                    BaseType_t xDoClear )
1298     {
1299         #if ( ipconfigMULTI_INTERFACE != 0 )
1300             struct freertos_addrinfo xHints;
1301             struct freertos_addrinfo * pxResult = NULL;
1302 
1303             memset( &( xHints ), 0, sizeof( xHints ) );
1304 
1305             if( xIPVersion == 6 )
1306             {
1307                 xHints.ai_family = FREERTOS_AF_INET6;
1308             }
1309             else
1310             {
1311                 xHints.ai_family = FREERTOS_AF_INET;
1312             }
1313         #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */
1314         FreeRTOS_printf( ( "pxDNSLookup: '%s' IPv%d %s DNS-clear = %s\n",
1315                            pcHost, ( int ) xIPVersion, ( xAsynchronous != 0 ) ? "Async" : "Sync", ( xDoClear != 0 ) ? "true" : "false" ) );
1316 
1317         if( xDoClear )
1318         {
1319             #if ( ipconfigUSE_DNS_CACHE != 0 )
1320                 {
1321                     FreeRTOS_dnsclear();
1322                     FreeRTOS_printf( ( "Clear DNS cache\n" ) );
1323                 }
1324             #endif /* ipconfigUSE_DNS_CACHE */
1325             #if ( ipconfigMULTI_INTERFACE != 0 )
1326                 FreeRTOS_ClearARP( NULL );
1327             #else
1328                 FreeRTOS_ClearARP();
1329             #endif
1330             FreeRTOS_printf( ( "Clear ARP cache\n" ) );
1331         }
1332 
1333         xDNSCount = 0;
1334         #if ( ipconfigMULTI_INTERFACE != 0 )
1335             #if ( ipconfigDNS_USE_CALLBACKS != 0 )
1336                 if( xAsynchronous != 0 )
1337                 {
1338                     uint32_t ulReturn;
1339                     xApplicationGetRandomNumber( &( ulReturn ) );
1340                     void * pvSearchID = ( void * ) ulReturn;
1341 
1342                     BaseType_t rc = FreeRTOS_getaddrinfo_a(
1343                         pcHost,    /* The node. */
1344                         NULL,      /* const char *pcService: ignored for now. */
1345                         &xHints,   /* If not NULL: preferences. */
1346                         &pxResult, /* An allocated struct, containing the results. */
1347                         vDNSEvent,
1348                         pvSearchID,
1349                         5000 );
1350 
1351                     FreeRTOS_printf( ( "dns query%d: '%s' = %d\n", ( int ) xIPVersion, pcHost, ( int ) rc ) );
1352 
1353                     if( pxResult != NULL )
1354                     {
1355                         show_addressinfo( pxResult );
1356                     }
1357                 }
1358                 else
1359             #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */
1360             {
1361                 #if ( ipconfigDNS_USE_CALLBACKS == 0 )
1362                     if( xAsynchronous != 0 )
1363                     {
1364                         FreeRTOS_printf( ( "ipconfigDNS_USE_CALLBACKS is not defined\n" ) );
1365                     }
1366                 #endif
1367                 BaseType_t rc = FreeRTOS_getaddrinfo(
1368                     pcHost,      /* The node. */
1369                     NULL,        /* const char *pcService: ignored for now. */
1370                     &xHints,     /* If not NULL: preferences. */
1371                     &pxResult ); /* An allocated struct, containing the results. */
1372                 FreeRTOS_printf( ( "FreeRTOS_getaddrinfo: rc %d\n", ( int ) rc ) );
1373 
1374                 if( pxResult != NULL )
1375                 {
1376                     show_addressinfo( pxResult );
1377                 }
1378 
1379                 if( rc != 0 )
1380                 {
1381                     FreeRTOS_printf( ( "dns query%d: '%s' No results\n", ( int ) xIPVersion, pcHost ) );
1382                 }
1383                 else
1384                 {
1385                     #if ( ipconfigUSE_IPv6 != 0 )
1386                         if( xIPVersion == 6 )
1387                         {
1388                             struct freertos_sockaddr * pxAddr6;
1389                             pxAddr6 = ( struct freertos_sockaddr * ) pxResult->ai_addr;
1390 
1391                             FreeRTOS_printf( ( "dns query%d: '%s' = %pip rc = %d\n", ( int ) xIPVersion, pcHost, pxAddr6->sin_address.xIP_IPv6.ucBytes, ( int ) rc ) );
1392                         }
1393                         else
1394                     #endif /* ipconfigUSE_IPv6 */
1395                     {
1396                         uint32_t luIPAddress = pxResult->ai_addr->sin_address.ulIP_IPv4;
1397                         FreeRTOS_printf( ( "dns query%d: '%s' = %lxip rc = %d\n", ( int ) xIPVersion, pcHost, FreeRTOS_ntohl( luIPAddress ), ( int ) rc ) );
1398                     }
1399                 }
1400             }
1401         #endif /* ipconfigMULTI_INTERFACE */
1402 
1403         #if ( ipconfigDNS_USE_CALLBACKS != 0 ) && ( ipconfigMULTI_INTERFACE != 0 )
1404             if( ( pxResult == NULL ) && ( xAsynchronous != 0 ) )
1405             {
1406                 #if ( ipconfigUSE_IPv6 != 0 )
1407                     IPv6_Address_t xAddress_IPv6;
1408                 #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1409                 uint32_t ulIpAddress;
1410                 int iCount;
1411 
1412                 for( iCount = 0; iCount < 10; iCount++ )
1413                 {
1414                     ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( 1000 ) );
1415 
1416                     if( xDNSCount != 0 )
1417                     {
1418                         break;
1419                     }
1420                 }
1421 
1422                 vTaskDelay( 333 );
1423                 pxResult = ( struct freertos_addrinfo * ) pvPortMalloc( sizeof( *pxResult ) );
1424 
1425                 if( pxResult != NULL )
1426                 {
1427                     memset( pxResult, '\0', sizeof( *pxResult ) );
1428                     pxResult->ai_canonname = pxResult->xPrivateStorage.ucName;
1429                     strncpy( pxResult->xPrivateStorage.ucName, pcHost, sizeof( pxResult->xPrivateStorage.ucName ) );
1430 
1431                     pxResult->ai_addr = &( pxResult->xPrivateStorage.sockaddr );
1432 
1433                     switch( xIPVersion )
1434                     {
1435                         #if ( ipconfigUSE_IPv4 != 0 )
1436                             case 4:
1437                                 #if ( ipconfigUSE_DNS_CACHE != 0 )
1438                                     ulIpAddress = FreeRTOS_dnslookup( pcHost );
1439                                     FreeRTOS_printf( ( "Lookup4 '%s' = %lxip\n", pcHost, FreeRTOS_ntohl( ulIpAddress ) ) );
1440                                     pxResult->ai_addr->sin_address.ulIP_IPv4 = ulIpAddress;
1441                                     pxResult->ai_family = FREERTOS_AF_INET4;
1442                                     pxResult->ai_addrlen = ipSIZE_OF_IPv4_ADDRESS;
1443                                 #endif
1444                                 break;
1445                         #endif /* ( ipconfigUSE_IPv4 != 0 ) */
1446 
1447                         #if ( ipconfigUSE_IPv6 != 0 )
1448                             case 6:
1449                                 memset( xAddress_IPv6.ucBytes, '\0', sizeof( xAddress_IPv6.ucBytes ) );
1450 
1451                                 if( xIPVersion == 6 )
1452                                 {
1453                                     FreeRTOS_dnslookup6( pcHost, &( xAddress_IPv6 ) );
1454                                     FreeRTOS_printf( ( "Lookup6 '%s' = %pip\n", pcHost, xAddress_IPv6.ucBytes ) );
1455                                     pxResult->ai_family = FREERTOS_AF_INET6;
1456                                     pxResult->ai_addrlen = ipSIZE_OF_IPv6_ADDRESS;
1457                                     memcpy( pxResult->xPrivateStorage.sockaddr.sin_address.xIP_IPv6.ucBytes, xAddress_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS );
1458                                 }
1459                                 break;
1460                         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1461 
1462                         default:
1463                             /* MISRA 16.4 Compliance */
1464                             FreeRTOS_debug_printf( ( "pxDNSLookup: Undefined IP Version Type \n" ) );
1465                             break;
1466                     }
1467                 }
1468             }
1469         #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) && ( ipconfigMULTI_INTERFACE != 0 ) */
1470         #if ( ipconfigMULTI_INTERFACE != 0 )
1471             /* Don't forget to call FreeRTOS_freeaddrinfo() */
1472             return pxResult;
1473         #else
1474             return 0;
1475         #endif
1476     }
1477 #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */
1478 /*-----------------------------------------------------------*/
1479 
1480 
vDNSEvent(const char * pcName,void * pvSearchID,struct freertos_addrinfo * pxAddrInfo)1481 static void vDNSEvent( const char * pcName,
1482                        void * pvSearchID,
1483                        struct freertos_addrinfo * pxAddrInfo )
1484 {
1485     ( void ) pvSearchID;
1486 
1487     if( pxAddrInfo == NULL )
1488     {
1489         FreeRTOS_printf( ( "vDNSEvent(%s) : nothing found\n", pcName ) );
1490     }
1491     else
1492     {
1493         FreeRTOS_printf( ( "vDNSEvent: family = %d\n", ( int ) pxAddrInfo->ai_family ) );
1494 
1495         switch( pxAddrInfo->ai_family )
1496         {
1497             #if ( ipconfigUSE_IPv4 != 0 )
1498                 case FREERTOS_AF_INET:
1499                    {
1500                        uint32_t ulIPaddress = pxAddrInfo->ai_addr->sin_address.ulIP_IPv4;
1501 
1502                        if( ulIPaddress == 0uL )
1503                        {
1504                            FreeRTOS_printf( ( "vDNSEvent/v4: '%s' timed out\n", pcName ) );
1505                        }
1506                        else
1507                        {
1508                            FreeRTOS_printf( ( "vDNSEvent/v4: found '%s' on %lxip\n", pcName, FreeRTOS_ntohl( ulIPaddress ) ) );
1509                        }
1510                    }
1511                    break;
1512             #endif /* ( ipconfigUSE_IPv4 != 0 ) */
1513 
1514             #if ( ipconfigUSE_IPv6 != 0 )
1515                 case FREERTOS_AF_INET6:
1516                    {
1517                        BaseType_t xIsEmpty = pdTRUE, xIndex;
1518 
1519                        for( xIndex = 0; xIndex < ( BaseType_t ) ARRAY_SIZE( pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes ); xIndex++ )
1520                        {
1521                            if( pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes[ xIndex ] != ( uint8_t ) 0u )
1522                            {
1523                                xIsEmpty = pdFALSE;
1524                                break;
1525                            }
1526                        }
1527 
1528                        if( xIsEmpty )
1529                        {
1530                            FreeRTOS_printf( ( "vDNSEvent/v6: '%s' timed out\n", pcName ) );
1531                        }
1532                        else
1533                        {
1534                            FreeRTOS_printf( ( "vDNSEvent/v6: found '%s' on %pip\n", pcName, pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes ) );
1535                        }
1536                    }
1537                    break;
1538             #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1539 
1540             default:
1541                 /* MISRA 16.4 Compliance */
1542                 FreeRTOS_debug_printf( ( "vDNSEvent: Undefined Family Type \n" ) );
1543                 break;
1544         }
1545     }
1546 
1547     if( xServerWorkTaskHandle != NULL )
1548     {
1549         xDNSCount++;
1550         xTaskNotifyGive( xServerWorkTaskHandle );
1551     }
1552 }
1553 
1554 /*-----------------------------------------------------------*/
1555 
1556 #if ( ipconfigMULTI_INTERFACE != 0 )
showEndPoint(NetworkEndPoint_t * pxEndPoint)1557     void showEndPoint( NetworkEndPoint_t * pxEndPoint )
1558     {
1559         int bWantDHCP, bWantRA;
1560         const char * pcMethodName;
1561         size_t uxDNSIndex;
1562 
1563         #if ( ipconfigUSE_DHCP != 0 )
1564             bWantDHCP = pxEndPoint->bits.bWantDHCP;
1565         #else
1566             bWantDHCP = 0;
1567         #endif
1568         #if ( ipconfigUSE_RA != 0 )
1569             bWantRA = pxEndPoint->bits.bWantRA;
1570         #else
1571             bWantRA = 0;
1572         #endif /* ( ipconfigUSE_RA != 0 ) */
1573 
1574         if( bWantDHCP != 0 )
1575         {
1576             pcMethodName = "DHCP";
1577         }
1578         else if( bWantRA != 0 )
1579         {
1580             pcMethodName = "RA";
1581         }
1582         else
1583         {
1584             pcMethodName = "static";
1585         }
1586 
1587         #if ( ipconfigUSE_IPv6 != 0 )
1588             if( pxEndPoint->bits.bIPv6 )
1589             {
1590                 IPv6_Address_t xPrefix;
1591 
1592                 /* Extract the prefix from the IP-address */
1593                 FreeRTOS_CreateIPv6Address( &( xPrefix ), &( pxEndPoint->ipv6_settings.xIPAddress ), pxEndPoint->ipv6_settings.uxPrefixLength, pdFALSE );
1594 
1595                 FreeRTOS_printf( ( "IP-address : %pip\n", pxEndPoint->ipv6_settings.xIPAddress.ucBytes ) );
1596 
1597                 if( memcmp( pxEndPoint->ipv6_defaults.xIPAddress.ucBytes, pxEndPoint->ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 )
1598                 {
1599                     FreeRTOS_printf( ( "Default IP : %pip\n", pxEndPoint->ipv6_defaults.xIPAddress.ucBytes ) );
1600                 }
1601 
1602                 FreeRTOS_printf( ( "End-point  : up = %s method %s\n", ( pxEndPoint->bits.bEndPointUp != 0 ) ? "yes" : "no", pcMethodName ) );
1603                 FreeRTOS_printf( ( "Prefix     : %pip/%d\n", xPrefix.ucBytes, ( int ) pxEndPoint->ipv6_settings.uxPrefixLength ) );
1604                 FreeRTOS_printf( ( "GW         : %pip\n", pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes ) );
1605 
1606                 for( uxDNSIndex = 0U; uxDNSIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT; uxDNSIndex++ )
1607                 {
1608                     FreeRTOS_printf( ( "DNS-%u      : %pip\n", uxDNSIndex, pxEndPoint->ipv6_settings.xDNSServerAddresses[ uxDNSIndex ].ucBytes ) );
1609                 }
1610             }
1611             else
1612         #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1613         {
1614             FreeRTOS_printf( ( "IP-address : %lxip\n",
1615                                FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulIPAddress ) ) );
1616 
1617             if( pxEndPoint->ipv4_settings.ulIPAddress != pxEndPoint->ipv4_defaults.ulIPAddress )
1618             {
1619                 FreeRTOS_printf( ( "Default IP : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_defaults.ulIPAddress ) ) );
1620             }
1621 
1622             FreeRTOS_printf( ( "End-point  : up = %s method %s\n", pxEndPoint->bits.bEndPointUp ? "yes" : "no", pcMethodName ) );
1623 
1624             FreeRTOS_printf( ( "Net mask   : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulNetMask ) ) );
1625             FreeRTOS_printf( ( "GW         : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulGatewayAddress ) ) );
1626 
1627             for( uxDNSIndex = 0U; uxDNSIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT; uxDNSIndex++ )
1628             {
1629                 FreeRTOS_printf( ( "DNS-%u      : %xip\n", uxDNSIndex, ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulDNSServerAddresses[ uxDNSIndex ] ) ) );
1630             }
1631 
1632             FreeRTOS_printf( ( "Broadcast  : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulBroadcastAddress ) ) );
1633         }
1634 
1635         FreeRTOS_printf( ( "MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
1636                            pxEndPoint->xMACAddress.ucBytes[ 0 ],
1637                            pxEndPoint->xMACAddress.ucBytes[ 1 ],
1638                            pxEndPoint->xMACAddress.ucBytes[ 2 ],
1639                            pxEndPoint->xMACAddress.ucBytes[ 3 ],
1640                            pxEndPoint->xMACAddress.ucBytes[ 4 ],
1641                            pxEndPoint->xMACAddress.ucBytes[ 5 ] ) );
1642         FreeRTOS_printf( ( " \n" ) );
1643     }
1644 #endif /* ipconfigMULTI_INTERFACE */
1645 /*-----------------------------------------------------------*/
1646 
clear_caches()1647 static void clear_caches()
1648 {
1649     #if ( ipconfigUSE_DNS_CACHE != 0 )
1650         {
1651             FreeRTOS_dnsclear();
1652             #if ( ipconfigUSE_IPv6 != 0 )
1653                 FreeRTOS_ClearND();
1654             #endif /* ( ipconfigUSE_IPv6 != 0 ) */
1655         }
1656     #endif /* ipconfigUSE_DNS_CACHE */
1657     #if ( ipconfigMULTI_INTERFACE != 0 )
1658         FreeRTOS_ClearARP( NULL );
1659     #else
1660         FreeRTOS_ClearARP();
1661     #endif
1662     FreeRTOS_printf( ( "Cleared caches.\n" ) );
1663 }
1664 /*-----------------------------------------------------------*/
1665