/* * FreeRTOS+TCP <DEVELOPMENT BRANCH> * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /** * @file plus_tcp_demo_cli.c * @brief This module will handle a set of commands that help with integration testing. * It is used for integration tests, both IPv4 and IPv6. */ /* Standard includes. */ #include <stdio.h> #include <time.h> #include <ctype.h> /* FreeRTOS includes. */ #include <FreeRTOS.h> #include "task.h" #include "timers.h" #include "queue.h" #include "semphr.h" #include "message_buffer.h" /* FreeRTOS+TCP includes. */ #include "FreeRTOS_IP.h" #include "FreeRTOS_Sockets.h" #include "FreeRTOS_DHCP.h" #include "FreeRTOS_DNS.h" #include "NetworkInterface.h" #include "NetworkBufferManagement.h" #include "FreeRTOS_ARP.h" #include "FreeRTOS_IP_Private.h" #if ( ipconfigMULTI_INTERFACE != 0 ) #include "FreeRTOS_Routing.h" #if ( ipconfigUSE_IPv6 != 0 ) #include "FreeRTOS_ND.h" #endif #endif #include "plus_tcp_demo_cli.h" #include "http_client_test.h" #if ( ipconfigUSE_NTP_DEMO != 0 ) #include "NTPDemo.h" #endif #if ( USE_IPERF != 0 ) #include "iperf_task.h" #endif int verboseLevel; static uint32_t ulWorkCount, ulLastWorkCount; extern SemaphoreHandle_t xServerSemaphore; extern uint64_t ullGetHighResolutionTime( void ); /* Some compilers do not support __attribute__( ( weak ) ) for a function declaration, * hence updating the declaration. */ #pragma WEAK ( ullGetHighResolutionTime ) uint64_t ullGetHighResolutionTime( void ) { /* In case you don't have a usec timer function. */ return xTaskGetTickCount(); } #define PING_TIMEOUT 100U typedef struct xCommandOptions { BaseType_t xDoClear; BaseType_t xIPVersion; /* Zero means: do not change version, otherwise 4 or 6. */ BaseType_t xAsynchronous; BaseType_t xLogging; } CommandOptions_t; size_t uxGetOptions( CommandOptions_t * pxOptions, const char ** ppcCommand ); int PING_COUNT_MAX = 10; static TaskHandle_t xServerWorkTaskHandle = NULL; extern void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier ); #if ( ipconfigUSE_IPv6 != 0 ) static IPv6_Address_t xPing6IPAddress; volatile BaseType_t xPing6Count = -1; #endif uint32_t ulPingIPAddress; size_t uxPingSize = 32U; volatile BaseType_t xPing4Count = -1; volatile BaseType_t xPingReady; static TickType_t uxPingTimes[ 2 ]; static int pingLogging = pdFALSE; static void handle_udp( char * pcBuffer ); static void handle_arpq( char * pcBuffer ); static void handle_dnsq( char * pcBuffer ); static void handle_ping( char * pcBuffer ); #if ( ipconfigUSE_NTP_DEMO != 0 ) static void handle_ntp( char * pcBuffer ); #endif static void handle_rand( char * pcBuffer ); static void handle_http( char * pcBuffer ); static void handle_whatismyipaddress( char * pcBuffer ); static void handle_ifconfig( char * pcBuffer ); static void handle_gw( char * pcBuffer ); static void handle_help( char * pcBuffer ); void handle_user_test( char * pcBuffer ); static void clear_caches( void ); static volatile BaseType_t xDNSCount = 0; static struct freertos_addrinfo * pxDNSLookup( char * pcHost, BaseType_t xIPVersion, BaseType_t xAsynchronous, BaseType_t xDoClear ); static void vDNSEvent( const char * pcName, void * pvSearchID, struct freertos_addrinfo * pxAddrInfo ); #if ( ipconfigMULTI_INTERFACE != 0 ) /* Defined in FreeRTOS_DNS.c */ void show_addressinfo( const struct freertos_addrinfo * pxAddress ); #endif /*-----------------------------------------------------------*/ typedef void ( * pfhandler ) ( char * /*pcBuffer */ ); struct xCommandCouple { char * pcCommand; size_t uxCommandLength; pfhandler pHandler; const char * pcHelp; }; static struct xCommandCouple xCommands[] = { { "arpq", 4U, handle_arpq, "Lookup the MAC-address of an IPv4 or IPv6 address." }, { "udp", 3U, handle_udp, "Send a text message to any UDP port." }, { "ping", 4U, handle_ping, "Look up a host and ping it 10 times." }, { "dnsq", 4U, handle_dnsq, "Look up a host using DNS, mDNS or LLMNR." }, { "rand", 4U, handle_rand, "Call the randomiser and print the resulting number.\n" }, { "http", 4U, handle_http, "Connect to port 80 of a host and download \"index.html\"\n" }, { "user_test", 9U, handle_user_test, "A user-supplied function \"handle_user_test()\" is called." }, { "whatismyip", 10U, handle_whatismyipaddress, "Print my IP-address\n" }, { "gw", 2U, handle_gw, "Show the configured gateway address\n" }, { "ifconfig", 8U, handle_ifconfig, "Show a few network parameters\n" }, { "help", 4U, handle_help, "Show this help\n" }, #if ( ipconfigUSE_NTP_DEMO != 0 ) { "ntp", 3U, handle_ntp, "Contact an NTP server and ask the time.\n" }, #endif }; static BaseType_t can_handle( char * pcBuffer, char * pcCommand, size_t uxLength, pfhandler phandler ) { BaseType_t xReturn = pdFALSE; if( strncmp( pcBuffer, pcCommand, uxLength ) == 0 ) { phandler( pcBuffer + uxLength ); xReturn = pdTRUE; } return xReturn; } /** * * @brief Create a task that runs the CLI. * @return zero when the command was recognised and handled. */ BaseType_t xHandleTestingCommand( char * pcBuffer, size_t uxBufferSize ) { /* Becomes true if the command is handled. */ BaseType_t xReturn = pdFALSE; ( void ) uxBufferSize; if( ulLastWorkCount == ulWorkCount ) { FreeRTOS_printf( ( "xHandleTestingCommand: the function xHandleTesting() was not called\n" ) ); } else { ulLastWorkCount = ulWorkCount; } if( xServerWorkTaskHandle == NULL ) { xServerWorkTaskHandle = xTaskGetCurrentTaskHandle(); } if( strncmp( pcBuffer, "ver", 3 ) == 0 ) { int level; if( sscanf( pcBuffer + 3, "%d", &level ) == 1 ) { verboseLevel = level; } FreeRTOS_printf( ( "Verbose level %d\n", verboseLevel ) ); xReturn = pdTRUE; } else { BaseType_t xIndex; for( xIndex = 0; xIndex < ARRAY_SIZE( xCommands ); xIndex++ ) { struct xCommandCouple * pxCommand = &( xCommands[ xIndex ] ); if( can_handle( pcBuffer, pxCommand->pcCommand, pxCommand->uxCommandLength, pxCommand->pHandler ) == pdTRUE ) { xReturn = pdTRUE; break; } } } return xReturn; } /*-----------------------------------------------------------*/ #if ( ipconfigMULTI_INTERFACE != 0 ) static void handle_ifconfig( char * pcBuffer ) { NetworkInterface_t * pxInterface; NetworkEndPoint_t * pxEndPoint; ( void ) pcBuffer; for( pxInterface = FreeRTOS_FirstNetworkInterface(); pxInterface != NULL; pxInterface = FreeRTOS_NextNetworkInterface( pxInterface ) ) { FreeRTOS_printf( ( "Interface %s\n", pxInterface->pcName ) ); for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { showEndPoint( pxEndPoint ); } } } #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */ static void handle_ifconfig( char * pcBuffer ) { ( void ) pcBuffer; FreeRTOS_printf( ( "IP-address %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetIPAddress() ) ) ); FreeRTOS_printf( ( "Netmask %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetNetmask() ) ) ); FreeRTOS_printf( ( "Gateway %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetGatewayAddress() ) ) ); FreeRTOS_printf( ( "DNS %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetDNSServerAddress() ) ) ); } #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */ /*-----------------------------------------------------------*/ static const char * pcARPReturnType( eARPLookupResult_t eResult ) { const char * pcReturn = "Unknown"; switch( eResult ) { case eARPCacheMiss: pcReturn = "Miss"; break; case eARPCacheHit: pcReturn = "Hit"; break; case eCantSendPacket: pcReturn = "Can not send"; break; } return pcReturn; } /*-----------------------------------------------------------*/ #if ( ipconfigUSE_IPv6 != 0 ) static NetworkEndPoint_t * pxFindEndpoint( IPv6_Address_t * pxAddress ) { NetworkEndPoint_t * pxEndpoint; for( pxEndpoint = FreeRTOS_FirstEndPoint( NULL ); pxEndpoint != NULL; pxEndpoint = FreeRTOS_NextEndPoint( NULL, pxEndpoint ) ) { if( memcmp( pxEndpoint->ipv6_settings.xGatewayAddress.ucBytes, pxAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) { break; } } return pxEndpoint; } /*-----------------------------------------------------------*/ #endif /* ( ipconfigUSE_IPv6 != 0 ) */ static void handle_udp( char * pcBuffer ) { /* e.g. "udp 192.168.2.11@1020 Hello world" */ CommandOptions_t xOptions; char * ptr = pcBuffer; char pcAtToken = '@'; char * pcToken = strchr( ptr, pcAtToken ); BaseType_t xIPType = 0; IP_Address_t xAddress; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); if( xOptions.xDoClear ) { clear_caches(); vNTPClearCache(); } if( pcToken != NULL ) { BaseType_t rc; *pcToken = 0; rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, ptr, ( void * ) &xAddress ); if( rc == pdPASS ) { xIPType = ipTYPE_IPv4; } else { rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, ptr, ( void * ) &xAddress ); if( rc == pdPASS ) { xIPType = ipTYPE_IPv6; } } *pcToken = pcAtToken; if( xIPType != 0 ) { unsigned uPort; if( sscanf( pcToken + 1, "%u", &uPort ) >= 1 ) { BaseType_t uxFamily; if( xIPType == ipTYPE_IPv6 ) { uxFamily = FREERTOS_AF_INET6; FreeRTOS_printf( ( "Send packet to UDP %pip port %u\n", xAddress.xIP_IPv6.ucBytes, uPort ) ); } else { uxFamily = FREERTOS_AF_INET; FreeRTOS_printf( ( "Send packet to UDP %xip port %u\n", ( unsigned ) FreeRTOS_ntohl( xAddress.ulIP_IPv4 ), uPort ) ); } static Socket_t xSocket = NULL; struct freertos_sockaddr xDestinationAddress; if( xSocket == NULL ) { struct freertos_sockaddr xSourceAddress; memset( &xSourceAddress, 0, sizeof xSourceAddress ); xSourceAddress.sin_family = uxFamily; xSourceAddress.sin_len = sizeof( xSourceAddress ); xSourceAddress.sin_port = FreeRTOS_htons( uPort ); xSocket = FreeRTOS_socket( uxFamily, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); FreeRTOS_bind( xSocket, &xSourceAddress, sizeof xSourceAddress ); } if( xSocket != NULL ) { size_t uxLength = strlen( pcBuffer ); memset( &xDestinationAddress, 0, sizeof xDestinationAddress ); if( xIPType == ipTYPE_IPv6 ) { memcpy( xDestinationAddress.sin_address.xIP_IPv6.ucBytes, xAddress.xIP_IPv6.ucBytes, 16 ); } else { xDestinationAddress.sin_address.ulIP_IPv4 = xAddress.ulIP_IPv4; } xDestinationAddress.sin_family = uxFamily; xDestinationAddress.sin_len = sizeof( xDestinationAddress ); xDestinationAddress.sin_port = FreeRTOS_htons( uPort ); char * pcCopy = ( char * ) pvPortMalloc( uxLength + 3 ); if( pcCopy != NULL ) { memcpy( pcCopy, pcBuffer, uxLength ); pcCopy[ uxLength + 0 ] = '\r'; pcCopy[ uxLength + 1 ] = '\n'; pcCopy[ uxLength + 2 ] = 0; rc = FreeRTOS_sendto( xSocket, pcCopy, uxLength + 2, 0, &xDestinationAddress, ( socklen_t ) sizeof( xDestinationAddress ) ); vPortFree( pcCopy ); } else { FreeRTOS_printf( ( "handle_udp: malloc failed\n" ) ); } vTaskDelay( pdMS_TO_TICKS( 500 ) ); } } } } if( ( pcToken == NULL ) || ( xIPType == 0 ) ) { FreeRTOS_printf( ( "handle_udp: bad parameters: '%s'\n", pcBuffer ) ); } } /*-----------------------------------------------------------*/ static void handle_arpq( char * pcBuffer ) { CommandOptions_t xOptions; char * ptr = pcBuffer; eARPLookupResult_t eResult; uint32_t ulIPAddress; uint32_t ulLookUpIP; MACAddress_t xMACAddress; NetworkEndPoint_t * pxEndPoint = NULL; BaseType_t xIPType = 0; IP_Address_t xAddress; IP_Address_t xLookupAddress; BaseType_t rc; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); if( xOptions.xDoClear ) { clear_caches(); vNTPClearCache(); } if( *ptr ) { char * pcBegin = ptr; for( ; *ptr != 0; ptr++ ) { if( !isxdigit( *ptr ) && ( *ptr != '.' ) && ( *ptr != ':' ) ) { *ptr = 0; break; } } memset( &xAddress, 0, sizeof xAddress ); rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcBegin, ( void * ) &xAddress ); if( rc == pdPASS ) { xIPType = ipTYPE_IPv4; } else { rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcBegin, ( void * ) &xAddress ); if( rc == pdPASS ) { xIPType = ipTYPE_IPv6; } } if( xIPType <= 0 ) { FreeRTOS_printf( ( "handle_arpq: bad arguments: '%s'\n", pcBuffer ) ); return; } ulIPAddress = xAddress.ulIP_IPv4; ulLookUpIP = ulIPAddress; xLookupAddress = xAddress; switch( xIPType ) { #if ( ipconfigUSE_IPv4 != 0 ) case ipTYPE_IPv4: eResult = eARPGetCacheEntry( &ulLookUpIP, &xMACAddress, &pxEndPoint ); FreeRTOS_printf( ( "ARPGetCacheEntry returns \"%s\" Look for %xip. Found end-point: %s\n", pcARPReturnType( eResult ), ( unsigned ) FreeRTOS_htonl( ulLookUpIP ), ( pxEndPoint != NULL ) ? "yes" : "no" ) ); break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case ipTYPE_IPv6: eResult = eNDGetCacheEntry( &( xLookupAddress.xIP_IPv6 ), &xMACAddress, &pxEndPoint ); FreeRTOS_printf( ( "ARPGetCacheEntry returns \"%s\" Look for %pip. Found end-point: %s\n", pcARPReturnType( eResult ), xAddress.xIP_IPv6.ucBytes, ( pxEndPoint != NULL ) ? "yes" : "no" ) ); break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) ); break; } if( ( eResult == eARPCacheMiss ) && ( pxEndPoint != NULL ) ) { size_t uxNeededSize = sizeof( ARPPacket_t ); if( xIPType == ipTYPE_IPv6 ) { uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPHeader_IPv6_t ); } NetworkBufferDescriptor_t * pxBuffer; switch( xIPType ) { #if ( ipconfigUSE_IPv4 != 0 ) case ipTYPE_IPv4: FreeRTOS_printf( ( "handle_arpq: Looking up %xip\n", ( unsigned ) FreeRTOS_ntohl( ulLookUpIP ) ) ); xARPWaitResolution( ulLookUpIP, 1000U ); break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case ipTYPE_IPv6: pxBuffer = pxGetNetworkBufferWithDescriptor( BUFFER_FROM_WHERE_CALL( 180 ) uxNeededSize, pdMS_TO_TICKS( 100U ) ); if( pxBuffer != NULL ) { UDPPacket_t * pxUDPPacket = ( ( UDPPacket_t * ) pxBuffer->pucEthernetBuffer ); /* 'ulLookUpIP' might be the IP-address of a gateway. */ memcpy( pxBuffer->xIPAddress.xIP_IPv6.ucBytes, xLookupAddress.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); pxUDPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE; pxBuffer->pxEndPoint = pxEndPoint; pxBuffer->pxInterface = pxBuffer->pxEndPoint->pxNetworkInterface; FreeRTOS_printf( ( "handle_arpq: Looking up %pip with%s end-point\n", pxBuffer->xIPAddress.xIP_IPv6.ucBytes, ( pxBuffer->pxEndPoint != NULL ) ? "" : "out" ) ); vNDSendNeighbourSolicitation( pxBuffer, &( pxBuffer->xIPAddress.xIP_IPv6 ) ); } else { FreeRTOS_printf( ( "handle_arpq: pxGetNetworkBufferWithDescriptor failed\n" ) ); } break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) ); break; } /* Let the IP-task do its work, and wait 500 ms. */ FreeRTOS_printf( ( "... Pause ...\n" ) ); vTaskDelay( pdMS_TO_TICKS( 500U ) ); switch( xIPType ) { #if ( ipconfigUSE_IPv4 != 0 ) case ipTYPE_IPv4: eResult = eARPGetCacheEntry( &ulLookUpIP, &xMACAddress, &pxEndPoint ); break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case ipTYPE_IPv6: eResult = eNDGetCacheEntry( &( xLookupAddress.xIP_IPv6 ), &xMACAddress, &pxEndPoint ); break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "handle_arpq: Undefined IP Type \n" ) ); break; } FreeRTOS_printf( ( "handle_arpq: after lookup: \"%s\"\n", pcARPReturnType( eResult ) ) ); } } } /*-----------------------------------------------------------*/ #if ( ipconfigMULTI_INTERFACE != 0 ) static void handle_dnsq( char * pcBuffer ) { CommandOptions_t xOptions; char * ptr = pcBuffer; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); if( *ptr ) { struct freertos_addrinfo * pxResult; pxResult = pxDNSLookup( ptr, xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xDoClear ); if( pxResult != NULL ) { FreeRTOS_freeaddrinfo( pxResult ); } } else { FreeRTOS_printf( ( "Usage: dnsq <name>\n" ) ); } } /*-----------------------------------------------------------*/ #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */ #if ( ( ipconfigMULTI_INTERFACE == 0 ) && ( ipconfigUSE_IPv4 != 0 ) ) static void handle_dnsq( char * pcBuffer ) { CommandOptions_t xOptions; char * ptr = pcBuffer; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); unsigned tmout = 4000; static unsigned searchID; if( *ptr ) { for( char * target = ptr; *target; target++ ) { if( isspace( *target ) ) { *target = '\0'; break; } } if( xOptions.xDoClear ) { #if ( ipconfigUSE_DNS_CACHE != 0 ) { FreeRTOS_dnsclear(); FreeRTOS_printf( ( "Clear DNS cache and ARP\n" ) ); } #endif /* ipconfigUSE_DNS_CACHE */ #if ( ipconfigMULTI_INTERFACE != 0 ) FreeRTOS_ClearARP( NULL ); #else FreeRTOS_ClearARP(); #endif FreeRTOS_printf( ( "Clear ARP cache\n" ) ); } FreeRTOS_printf( ( "DNS query: '%s'\n", ptr ) ); { uint32_t ulGatewayAddress; FreeRTOS_GetAddressConfiguration( NULL, NULL, &( ulGatewayAddress ), NULL ); if( xIsIPInARPCache( ulGatewayAddress ) == pdFALSE ) { xARPWaitResolution( ulGatewayAddress, pdMS_TO_TICKS( 5000U ) ); } } #if ( ipconfigDNS_USE_CALLBACKS != 0 ) if( xOptions.xAsynchronous != 0 ) { BaseType_t iCount; TickType_t uxWaitTime = 1000U; xDNSCount = 0; ip = FreeRTOS_gethostbyname_a( ptr, vDNSEvent, ( void * ) ++searchID, tmout ); for( iCount = 0; iCount < 10; iCount++ ) { ulTaskNotifyTake( pdTRUE, uxWaitTime ); if( xDNSCount != 0 ) { break; } } } else #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ { #if ( ipconfigDNS_USE_CALLBACKS == 0 ) if( xOptions.xAsynchronous != 0 ) { FreeRTOS_printf( ( "Asynchronous DNS requested but not installed.\n" ) ); } #endif ip = FreeRTOS_gethostbyname( ptr ); } FreeRTOS_printf( ( "%s : %xip\n", ptr, ( unsigned ) FreeRTOS_ntohl( ip ) ) ); #if ( ipconfigUSE_DNS_CACHE == 0 ) { FreeRTOS_printf( ( "DNS caching not enabled\n" ) ); } #else { uint32_t ulFirstIPAddress = 0U; BaseType_t xIndex; for( xIndex = 0; xIndex < ( BaseType_t ) ipconfigDNS_CACHE_ENTRIES; xIndex++ ) { /* Note: 'FreeRTOS_dnslookup' is only defined when * 'ipconfigUSE_DNS_CACHE' is enabled. */ uint32_t ulThisIPAddress = FreeRTOS_dnslookup( ptr ); if( xIndex == 0 ) { ulFirstIPAddress = ulThisIPAddress; } else if( ulFirstIPAddress == ulThisIPAddress ) { break; } FreeRTOS_printf( ( "Cache[%d]: %xip\n", ( int ) xIndex, ( unsigned ) FreeRTOS_ntohl( ulThisIPAddress ) ) ); } } #endif /* ( ipconfigUSE_DNS_CACHE == 0 ) */ } else { FreeRTOS_printf( ( "Usage: dnsquery <name>\n" ) ); } } /*-----------------------------------------------------------*/ #endif /* ( ( ipconfigMULTI_INTERFACE == 0 ) && ( ipconfigUSE_IPv4 != 0 ) ) */ static void handle_rand( char * pcBuffer ) { uint32_t ulNumber = 0x5a5a5a5a; BaseType_t rc = xApplicationGetRandomNumber( &ulNumber ); ( void ) pcBuffer; if( rc == pdPASS ) { char buffer[ 33 ]; int index; uint32_t ulMask = 0x80000000uL; for( index = 0; index < 32; index++ ) { buffer[ index ] = ( ( ulNumber & ulMask ) != 0 ) ? '1' : '0'; ulMask >>= 1; } buffer[ index ] = '\0'; FreeRTOS_printf( ( "Random %08lx (%s)\n", ulNumber, buffer ) ); } else { FreeRTOS_printf( ( "Random failed\n" ) ); } } /*-----------------------------------------------------------*/ size_t uxGetOptions( CommandOptions_t * pxOptions, const char ** ppcCommand ) { size_t uxLength = 0U; const char * pcCommand = *ppcCommand; memset( pxOptions, 0, sizeof( *pxOptions ) ); pxOptions->xIPVersion = 4; while( ( pcCommand[ uxLength ] != 0 ) && ( !isspace( ( uint8_t ) pcCommand[ uxLength ] ) ) ) { switch( pcCommand[ uxLength ] ) { case 'a': pxOptions->xAsynchronous = pdTRUE; break; case 'c': pxOptions->xDoClear = pdTRUE; break; case 'v': pxOptions->xLogging = pdTRUE; break; case '4': pxOptions->xIPVersion = 4; break; case '6': pxOptions->xIPVersion = 6; break; } uxLength++; } if( uxLength > 0U ) { *ppcCommand = &( pcCommand[ uxLength ] ); } while( isspace( ( uint8_t ) ( *ppcCommand )[ 0 ] ) ) { ( *ppcCommand )++; } return uxLength; } #if ( ipconfigUSE_NTP_DEMO != 0 ) static void handle_ntp( char * pcBuffer ) { CommandOptions_t xOptions; char * ptr = pcBuffer; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); if( xOptions.xDoClear ) { clear_caches(); vNTPClearCache(); } vNTPSetNTPType( xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xLogging ); /* vStartNTPTask() may be called multiple times. */ vStartNTPTask( configMINIMAL_STACK_SIZE * 12, tskIDLE_PRIORITY + 1 ); } #endif /* if ( ipconfigUSE_NTP_DEMO != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) static void handle_whatismyipaddress( char * pcBuffer ) { NetworkEndPoint_t * pxEndPoint; ( void ) pcBuffer; FreeRTOS_printf( ( "Showing all end-points\n" ) ); for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) ) { #if ( ipconfigUSE_IPv6 != 0 ) if( pxEndPoint->bits.bIPv6 ) { FreeRTOS_printf( ( "IPv6: %pip on '%s'\n", pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxEndPoint->pxNetworkInterface->pcName ) ); } else #endif { FreeRTOS_printf( ( "IPv4: %xip on '%s'\n", ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulIPAddress ), pxEndPoint->pxNetworkInterface->pcName ) ); } } } #else /* if ( ipconfigUSE_IPv6 != 0 ) */ static void handle_whatismyipaddress( char * pcBuffer ) { ( void ) pcBuffer; FreeRTOS_printf( ( "IPv4: %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetIPAddress() ) ) ); } #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ static void handle_help( char * pcBuffer ) { BaseType_t xIndex; ( void ) pcBuffer; FreeRTOS_printf( ( "Available commands:\n" ) ); for( xIndex = 0; xIndex < ARRAY_SIZE( xCommands ); xIndex++ ) { FreeRTOS_printf( ( "%-11.11s: %s\n", xCommands[ xIndex ].pcCommand, xCommands[ xIndex ].pcHelp ) ); } } #if ( ipconfigMULTI_INTERFACE != 0 ) static void handle_gw( char * pcBuffer ) { NetworkEndPoint_t * pxEndPoint; ( void ) pcBuffer; FreeRTOS_printf( ( "Showing all gateways\n" ) ); for( pxEndPoint = FreeRTOS_FirstEndPoint( NULL ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( NULL, pxEndPoint ) ) { #if ( ipconfigUSE_IPv6 != 0 ) if( pxEndPoint->bits.bIPv6 ) { if( memcmp( pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, FreeRTOS_in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) { FreeRTOS_printf( ( "IPv6: %pip on '%s'\n", pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, pxEndPoint->pxNetworkInterface->pcName ) ); } } else #endif { if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) { FreeRTOS_printf( ( "IPv4: %xip on '%s'\n", ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulGatewayAddress ), pxEndPoint->pxNetworkInterface->pcName ) ); } } } } #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */ static void handle_gw( char * pcBuffer ) { ( void ) pcBuffer; FreeRTOS_printf( ( "Gateway: %xip\n", ( unsigned ) FreeRTOS_ntohl( FreeRTOS_GetGatewayAddress() ) ) ); } #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ #if ( ipconfigMULTI_INTERFACE != 0 ) static void handle_ping( char * pcBuffer ) { struct freertos_addrinfo * pxDNSResult = NULL; char * ptr = pcBuffer; CommandOptions_t xOptions; IP_Address_t xAddress; BaseType_t xResult; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); pingLogging = xOptions.xLogging; char * pcHostname = ptr; if( *pcHostname == '\0' ) { FreeRTOS_printf( ( "handle_ping: please provide a hostname of an IP-address\n" ) ); return; } memset( &xAddress, 0, sizeof xAddress ); xResult = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcHostname, ( void * ) &xAddress ); if( xResult == pdPASS ) { xOptions.xIPVersion = 4; } else { xResult = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcHostname, ( void * ) &xAddress ); if( xResult == pdPASS ) { xOptions.xIPVersion = 6; } } if( xOptions.xIPVersion == 6 ) { FreeRTOS_printf( ( "ping6: looking up name '%s' (%pip)\n", pcHostname, xAddress.xIP_IPv6.ucBytes ) ); } else { FreeRTOS_printf( ( "ping4: looking up name '%s' (%xip)\n", pcHostname, ( unsigned ) FreeRTOS_ntohl( xAddress.ulIP_IPv4 ) ) ); } if( xOptions.xDoClear ) { clear_caches(); } FreeRTOS_printf( ( "Calling pxDNSLookup\n" ) ); pxDNSResult = pxDNSLookup( pcHostname, xOptions.xIPVersion, xOptions.xAsynchronous, xOptions.xDoClear ); if( pxDNSResult != NULL ) { switch( xOptions.xIPVersion ) { #if ( ipconfigUSE_IPv4 != 0 ) case 4: FreeRTOS_printf( ( "ping4 to '%s' (%xip)\n", pcHostname, ( unsigned ) FreeRTOS_ntohl( pxDNSResult->ai_addr->sin_address.ulIP_IPv4 ) ) ); xPing4Count = 0; #if ( ipconfigUSE_IPv6 != 0 ) xPing6Count = -1; #endif ulPingIPAddress = pxDNSResult->ai_addr->sin_address.ulIP_IPv4; xARPWaitResolution( ulPingIPAddress, pdMS_TO_TICKS( 5000U ) ); FreeRTOS_SendPingRequest( ulPingIPAddress, uxPingSize, PING_TIMEOUT ); uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case 6: FreeRTOS_printf( ( "ping6 to '%s' (%pip)\n", pcHostname, pxDNSResult->ai_addr->sin_address.xIP_IPv6.ucBytes ) ); xPing4Count = -1; xPing6Count = 0; memcpy( xPing6IPAddress.ucBytes, pxDNSResult->ai_addr->sin_address.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); FreeRTOS_SendPingRequestIPv6( &xPing6IPAddress, uxPingSize, PING_TIMEOUT ); uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "handle_ping: Undefined IP Type \n" ) ); break; } } else { FreeRTOS_printf( ( "ping -%d: '%s' not found\n", ( int ) xOptions.xIPVersion, ptr ) ); } } /*-----------------------------------------------------------*/ #else /* ipconfigMULTI_INTERFACE != 0 */ static void handle_ping( char * pcBuffer ) { uint32_t ulIPAddress; char * ptr = pcBuffer; PING_COUNT_MAX = 10; CommandOptions_t xOptions; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); pingLogging = xOptions.xLogging; FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL ); if( *ptr != 0 ) { char * rest = strchr( ptr, ' ' ); if( rest ) { *( rest++ ) = '\0'; } ulIPAddress = FreeRTOS_inet_addr( ptr ); while( *ptr && !isspace( *ptr ) ) { ptr++; } unsigned count; if( ( rest != NULL ) && ( sscanf( rest, "%u", &count ) > 0 ) ) { PING_COUNT_MAX = count; } } FreeRTOS_printf( ( "ping to %xip\n", ( unsigned ) FreeRTOS_htonl( ulIPAddress ) ) ); ulPingIPAddress = ulIPAddress; xPing4Count = 0; #if ( ipconfigUSE_IPv6 != 0 ) xPing6Count = -1; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ xPingReady = pdFALSE; if( xOptions.xDoClear ) { #if ( ipconfigMULTI_INTERFACE != 0 ) FreeRTOS_ClearARP( NULL ); #else FreeRTOS_ClearARP(); #endif FreeRTOS_printf( ( "Clearing ARP cache\n" ) ); } FreeRTOS_SendPingRequest( ulIPAddress, uxPingSize, PING_TIMEOUT ); uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); } #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */ /*-----------------------------------------------------------*/ static void handle_http( char * pcBuffer ) { char * ptr = pcBuffer; CommandOptions_t xOptions; pingLogging = pdFALSE; uxGetOptions( &( xOptions ), ( const char ** ) &( ptr ) ); if( xOptions.xIPVersion == 6 ) { FreeRTOS_printf( ( "http IPv6\n" ) ); } if( *ptr != 0 ) { unsigned portNr = 80U; char * pcHost = ptr; char * pcFileName; char * next = ptr; while( ( *next != 0 ) && ( isspace( *next ) == 0 ) ) { next++; } while( isspace( *next ) != 0 ) { /* Erase the space. */ *next = 0; next++; } pcFileName = next; while( ( *next != 0 ) && ( isspace( *next ) == 0 ) ) { next++; } while( isspace( *next ) != 0 ) { /* Erase the space. */ *next = 0; next++; } if( isdigit( *next ) ) { ( void ) sscanf( next, "%u", &portNr ); } if( xOptions.xDoClear ) { clear_caches(); } { IP_Address_t xAddress; BaseType_t rc = FreeRTOS_inet_pton( FREERTOS_AF_INET6, pcHost, ( void * ) &xAddress ); if( rc == pdPASS ) { xOptions.xIPVersion = 6; } else { rc = FreeRTOS_inet_pton( FREERTOS_AF_INET4, pcHost, ( void * ) &xAddress ); if( rc == pdPASS ) { xOptions.xIPVersion = 4; } } } /* Get '192.168.2.11' from '/index.html' at port 33001 */ FreeRTOS_printf( ( "Get '%s' from '%s' at port %u\n", pcFileName, pcHost, portNr ) ); #if ( USE_ECHO_TASK != 0 ) vStartHTTPClientTest( configMINIMAL_STACK_SIZE * 8, tskIDLE_PRIORITY + 1 ); wakeupHTTPClient( 0U, pcHost, pcFileName, portNr, xOptions.xIPVersion ); #else FreeRTOS_printf( ( "handle_http: please define 'USE_ECHO_TASK'\n" ) ); #endif } else { FreeRTOS_printf( ( "Usage: http <hostname>\n" ) ); } } /*-----------------------------------------------------------*/ void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier ) { uxPingTimes[ 1 ] = ( TickType_t ) ullGetHighResolutionTime(); if( ( xPing4Count >= 0 ) && ( xPing4Count < PING_COUNT_MAX ) ) { xPing4Count++; if( pingLogging || ( xPing4Count == PING_COUNT_MAX ) ) { FreeRTOS_printf( ( "Received reply %d: status %d ID %04x\n", ( int ) xPing4Count, ( int ) eStatus, usIdentifier ) ); } } #if ( ipconfigUSE_IPv6 != 0 ) if( ( xPing6Count >= 0 ) && ( xPing6Count < PING_COUNT_MAX ) ) { xPing6Count++; if( pingLogging || ( xPing6Count == PING_COUNT_MAX ) ) { FreeRTOS_printf( ( "Received reply %d: status %d ID %04x\n", ( int ) xPing6Count, ( int ) eStatus, usIdentifier ) ); } } #endif xPingReady = pdTRUE; if( xServerSemaphore != NULL ) { xSemaphoreGive( xServerSemaphore ); } } /*-----------------------------------------------------------*/ void xHandleTesting() { /* A counter to check if the application calls this work function. * It should be called regularly from the application. * he application will block on 'xServerSemaphore'. */ ulWorkCount++; if( xPingReady ) { TickType_t uxTimeTicks = uxPingTimes[ 1 ] - uxPingTimes[ 0 ]; #if ( ipconfigUSE_IPv6 != 0 ) FreeRTOS_printf( ( "xPingReady %d xPing4 %d xPing6 %d Delta %u\n", ( int ) xPingReady, ( int ) xPing4Count, ( int ) xPing6Count, ( unsigned ) uxTimeTicks ) ); #else FreeRTOS_printf( ( "xPingReady %d xPing4 %d Delta %u\n", ( int ) xPingReady, ( int ) xPing4Count, ( unsigned ) uxTimeTicks ) ); #endif xPingReady = pdFALSE; if( ( xPing4Count >= 0 ) && ( xPing4Count < PING_COUNT_MAX ) ) { /* 10 bytes, 100 clock ticks. */ FreeRTOS_SendPingRequest( ulPingIPAddress, uxPingSize, PING_TIMEOUT ); uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); } #if ( ipconfigUSE_IPv6 != 0 ) if( ( xPing6Count >= 0 ) && ( xPing6Count < PING_COUNT_MAX ) ) { FreeRTOS_SendPingRequestIPv6( &xPing6IPAddress, uxPingSize, PING_TIMEOUT ); uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); } #endif } } /*-----------------------------------------------------------*/ #if ( ipconfigMULTI_INTERFACE != 0 ) static struct freertos_addrinfo * pxDNSLookup( char * pcHost, BaseType_t xIPVersion, BaseType_t xAsynchronous, BaseType_t xDoClear ) { #if ( ipconfigMULTI_INTERFACE != 0 ) struct freertos_addrinfo xHints; struct freertos_addrinfo * pxResult = NULL; memset( &( xHints ), 0, sizeof( xHints ) ); if( xIPVersion == 6 ) { xHints.ai_family = FREERTOS_AF_INET6; } else { xHints.ai_family = FREERTOS_AF_INET; } #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ FreeRTOS_printf( ( "pxDNSLookup: '%s' IPv%d %s DNS-clear = %s\n", pcHost, ( int ) xIPVersion, ( xAsynchronous != 0 ) ? "Async" : "Sync", ( xDoClear != 0 ) ? "true" : "false" ) ); if( xDoClear ) { #if ( ipconfigUSE_DNS_CACHE != 0 ) { FreeRTOS_dnsclear(); FreeRTOS_printf( ( "Clear DNS cache\n" ) ); } #endif /* ipconfigUSE_DNS_CACHE */ #if ( ipconfigMULTI_INTERFACE != 0 ) FreeRTOS_ClearARP( NULL ); #else FreeRTOS_ClearARP(); #endif FreeRTOS_printf( ( "Clear ARP cache\n" ) ); } xDNSCount = 0; #if ( ipconfigMULTI_INTERFACE != 0 ) #if ( ipconfigDNS_USE_CALLBACKS != 0 ) if( xAsynchronous != 0 ) { uint32_t ulReturn; xApplicationGetRandomNumber( &( ulReturn ) ); void * pvSearchID = ( void * ) ulReturn; BaseType_t rc = FreeRTOS_getaddrinfo_a( pcHost, /* The node. */ NULL, /* const char *pcService: ignored for now. */ &xHints, /* If not NULL: preferences. */ &pxResult, /* An allocated struct, containing the results. */ vDNSEvent, pvSearchID, 5000 ); FreeRTOS_printf( ( "dns query%d: '%s' = %d\n", ( int ) xIPVersion, pcHost, ( int ) rc ) ); if( pxResult != NULL ) { show_addressinfo( pxResult ); } } else #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ { #if ( ipconfigDNS_USE_CALLBACKS == 0 ) if( xAsynchronous != 0 ) { FreeRTOS_printf( ( "ipconfigDNS_USE_CALLBACKS is not defined\n" ) ); } #endif BaseType_t rc = FreeRTOS_getaddrinfo( pcHost, /* The node. */ NULL, /* const char *pcService: ignored for now. */ &xHints, /* If not NULL: preferences. */ &pxResult ); /* An allocated struct, containing the results. */ FreeRTOS_printf( ( "FreeRTOS_getaddrinfo: rc %d\n", ( int ) rc ) ); if( pxResult != NULL ) { show_addressinfo( pxResult ); } if( rc != 0 ) { FreeRTOS_printf( ( "dns query%d: '%s' No results\n", ( int ) xIPVersion, pcHost ) ); } else { #if ( ipconfigUSE_IPv6 != 0 ) if( xIPVersion == 6 ) { struct freertos_sockaddr * pxAddr6; pxAddr6 = ( struct freertos_sockaddr * ) pxResult->ai_addr; FreeRTOS_printf( ( "dns query%d: '%s' = %pip rc = %d\n", ( int ) xIPVersion, pcHost, pxAddr6->sin_address.xIP_IPv6.ucBytes, ( int ) rc ) ); } else #endif /* ipconfigUSE_IPv6 */ { uint32_t luIPAddress = pxResult->ai_addr->sin_address.ulIP_IPv4; FreeRTOS_printf( ( "dns query%d: '%s' = %lxip rc = %d\n", ( int ) xIPVersion, pcHost, FreeRTOS_ntohl( luIPAddress ), ( int ) rc ) ); } } } #endif /* ipconfigMULTI_INTERFACE */ #if ( ipconfigDNS_USE_CALLBACKS != 0 ) && ( ipconfigMULTI_INTERFACE != 0 ) if( ( pxResult == NULL ) && ( xAsynchronous != 0 ) ) { #if ( ipconfigUSE_IPv6 != 0 ) IPv6_Address_t xAddress_IPv6; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ uint32_t ulIpAddress; int iCount; for( iCount = 0; iCount < 10; iCount++ ) { ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( 1000 ) ); if( xDNSCount != 0 ) { break; } } vTaskDelay( 333 ); pxResult = ( struct freertos_addrinfo * ) pvPortMalloc( sizeof( *pxResult ) ); if( pxResult != NULL ) { memset( pxResult, '\0', sizeof( *pxResult ) ); pxResult->ai_canonname = pxResult->xPrivateStorage.ucName; strncpy( pxResult->xPrivateStorage.ucName, pcHost, sizeof( pxResult->xPrivateStorage.ucName ) ); pxResult->ai_addr = &( pxResult->xPrivateStorage.sockaddr ); switch( xIPVersion ) { #if ( ipconfigUSE_IPv4 != 0 ) case 4: #if ( ipconfigUSE_DNS_CACHE != 0 ) ulIpAddress = FreeRTOS_dnslookup( pcHost ); FreeRTOS_printf( ( "Lookup4 '%s' = %lxip\n", pcHost, FreeRTOS_ntohl( ulIpAddress ) ) ); pxResult->ai_addr->sin_address.ulIP_IPv4 = ulIpAddress; pxResult->ai_family = FREERTOS_AF_INET4; pxResult->ai_addrlen = ipSIZE_OF_IPv4_ADDRESS; #endif break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case 6: memset( xAddress_IPv6.ucBytes, '\0', sizeof( xAddress_IPv6.ucBytes ) ); if( xIPVersion == 6 ) { FreeRTOS_dnslookup6( pcHost, &( xAddress_IPv6 ) ); FreeRTOS_printf( ( "Lookup6 '%s' = %pip\n", pcHost, xAddress_IPv6.ucBytes ) ); pxResult->ai_family = FREERTOS_AF_INET6; pxResult->ai_addrlen = ipSIZE_OF_IPv6_ADDRESS; memcpy( pxResult->xPrivateStorage.sockaddr.sin_address.xIP_IPv6.ucBytes, xAddress_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "pxDNSLookup: Undefined IP Version Type \n" ) ); break; } } } #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) && ( ipconfigMULTI_INTERFACE != 0 ) */ #if ( ipconfigMULTI_INTERFACE != 0 ) /* Don't forget to call FreeRTOS_freeaddrinfo() */ return pxResult; #else return 0; #endif } #endif /* ( ipconfigMULTI_INTERFACE != 0 ) */ /*-----------------------------------------------------------*/ static void vDNSEvent( const char * pcName, void * pvSearchID, struct freertos_addrinfo * pxAddrInfo ) { ( void ) pvSearchID; if( pxAddrInfo == NULL ) { FreeRTOS_printf( ( "vDNSEvent(%s) : nothing found\n", pcName ) ); } else { FreeRTOS_printf( ( "vDNSEvent: family = %d\n", ( int ) pxAddrInfo->ai_family ) ); switch( pxAddrInfo->ai_family ) { #if ( ipconfigUSE_IPv4 != 0 ) case FREERTOS_AF_INET: { uint32_t ulIPaddress = pxAddrInfo->ai_addr->sin_address.ulIP_IPv4; if( ulIPaddress == 0uL ) { FreeRTOS_printf( ( "vDNSEvent/v4: '%s' timed out\n", pcName ) ); } else { FreeRTOS_printf( ( "vDNSEvent/v4: found '%s' on %lxip\n", pcName, FreeRTOS_ntohl( ulIPaddress ) ) ); } } break; #endif /* ( ipconfigUSE_IPv4 != 0 ) */ #if ( ipconfigUSE_IPv6 != 0 ) case FREERTOS_AF_INET6: { BaseType_t xIsEmpty = pdTRUE, xIndex; for( xIndex = 0; xIndex < ( BaseType_t ) ARRAY_SIZE( pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes ); xIndex++ ) { if( pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes[ xIndex ] != ( uint8_t ) 0u ) { xIsEmpty = pdFALSE; break; } } if( xIsEmpty ) { FreeRTOS_printf( ( "vDNSEvent/v6: '%s' timed out\n", pcName ) ); } else { FreeRTOS_printf( ( "vDNSEvent/v6: found '%s' on %pip\n", pcName, pxAddrInfo->ai_addr->sin_address.xIP_IPv6.ucBytes ) ); } } break; #endif /* ( ipconfigUSE_IPv6 != 0 ) */ default: /* MISRA 16.4 Compliance */ FreeRTOS_debug_printf( ( "vDNSEvent: Undefined Family Type \n" ) ); break; } } if( xServerWorkTaskHandle != NULL ) { xDNSCount++; xTaskNotifyGive( xServerWorkTaskHandle ); } } /*-----------------------------------------------------------*/ #if ( ipconfigMULTI_INTERFACE != 0 ) void showEndPoint( NetworkEndPoint_t * pxEndPoint ) { int bWantDHCP, bWantRA; const char * pcMethodName; size_t uxDNSIndex; #if ( ipconfigUSE_DHCP != 0 ) bWantDHCP = pxEndPoint->bits.bWantDHCP; #else bWantDHCP = 0; #endif #if ( ipconfigUSE_RA != 0 ) bWantRA = pxEndPoint->bits.bWantRA; #else bWantRA = 0; #endif /* ( ipconfigUSE_RA != 0 ) */ if( bWantDHCP != 0 ) { pcMethodName = "DHCP"; } else if( bWantRA != 0 ) { pcMethodName = "RA"; } else { pcMethodName = "static"; } #if ( ipconfigUSE_IPv6 != 0 ) if( pxEndPoint->bits.bIPv6 ) { IPv6_Address_t xPrefix; /* Extract the prefix from the IP-address */ FreeRTOS_CreateIPv6Address( &( xPrefix ), &( pxEndPoint->ipv6_settings.xIPAddress ), pxEndPoint->ipv6_settings.uxPrefixLength, pdFALSE ); FreeRTOS_printf( ( "IP-address : %pip\n", pxEndPoint->ipv6_settings.xIPAddress.ucBytes ) ); if( memcmp( pxEndPoint->ipv6_defaults.xIPAddress.ucBytes, pxEndPoint->ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) { FreeRTOS_printf( ( "Default IP : %pip\n", pxEndPoint->ipv6_defaults.xIPAddress.ucBytes ) ); } FreeRTOS_printf( ( "End-point : up = %s method %s\n", ( pxEndPoint->bits.bEndPointUp != 0 ) ? "yes" : "no", pcMethodName ) ); FreeRTOS_printf( ( "Prefix : %pip/%d\n", xPrefix.ucBytes, ( int ) pxEndPoint->ipv6_settings.uxPrefixLength ) ); FreeRTOS_printf( ( "GW : %pip\n", pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes ) ); for( uxDNSIndex = 0U; uxDNSIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT; uxDNSIndex++ ) { FreeRTOS_printf( ( "DNS-%u : %pip\n", uxDNSIndex, pxEndPoint->ipv6_settings.xDNSServerAddresses[ uxDNSIndex ].ucBytes ) ); } } else #endif /* ( ipconfigUSE_IPv6 != 0 ) */ { FreeRTOS_printf( ( "IP-address : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulIPAddress ) ) ); if( pxEndPoint->ipv4_settings.ulIPAddress != pxEndPoint->ipv4_defaults.ulIPAddress ) { FreeRTOS_printf( ( "Default IP : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_defaults.ulIPAddress ) ) ); } FreeRTOS_printf( ( "End-point : up = %s method %s\n", pxEndPoint->bits.bEndPointUp ? "yes" : "no", pcMethodName ) ); FreeRTOS_printf( ( "Net mask : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulNetMask ) ) ); FreeRTOS_printf( ( "GW : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulGatewayAddress ) ) ); for( uxDNSIndex = 0U; uxDNSIndex < ipconfigENDPOINT_DNS_ADDRESS_COUNT; uxDNSIndex++ ) { FreeRTOS_printf( ( "DNS-%u : %xip\n", uxDNSIndex, ( unsigned ) FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulDNSServerAddresses[ uxDNSIndex ] ) ) ); } FreeRTOS_printf( ( "Broadcast : %lxip\n", FreeRTOS_ntohl( pxEndPoint->ipv4_settings.ulBroadcastAddress ) ) ); } FreeRTOS_printf( ( "MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n", pxEndPoint->xMACAddress.ucBytes[ 0 ], pxEndPoint->xMACAddress.ucBytes[ 1 ], pxEndPoint->xMACAddress.ucBytes[ 2 ], pxEndPoint->xMACAddress.ucBytes[ 3 ], pxEndPoint->xMACAddress.ucBytes[ 4 ], pxEndPoint->xMACAddress.ucBytes[ 5 ] ) ); FreeRTOS_printf( ( " \n" ) ); } #endif /* ipconfigMULTI_INTERFACE */ /*-----------------------------------------------------------*/ static void clear_caches() { #if ( ipconfigUSE_DNS_CACHE != 0 ) { FreeRTOS_dnsclear(); #if ( ipconfigUSE_IPv6 != 0 ) FreeRTOS_ClearND(); #endif /* ( ipconfigUSE_IPv6 != 0 ) */ } #endif /* ipconfigUSE_DNS_CACHE */ #if ( ipconfigMULTI_INTERFACE != 0 ) FreeRTOS_ClearARP( NULL ); #else FreeRTOS_ClearARP(); #endif FreeRTOS_printf( ( "Cleared caches.\n" ) ); } /*-----------------------------------------------------------*/