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