From ab5bb6b57a4c2cec1f2e3fe2262994bb736347e1 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Mon, 20 Feb 2023 17:02:39 +0800 Subject: [PATCH 1/8] Updating tcp utilities --- tools/tcp_utilities/NTPDemo.c | 693 +++++++ tools/tcp_utilities/date_and_time.c | 136 ++ tools/tcp_utilities/http_client_test.c | 616 +++++++ tools/tcp_utilities/include/NTPDemo.c | 693 +++++++ tools/tcp_utilities/include/NTPDemo.h | 55 + tools/tcp_utilities/include/date_and_time.h | 94 + .../tcp_utilities/include/http_client_test.h | 23 + tools/tcp_utilities/include/ntpClient.h | 103 ++ .../tcp_utilities/include/plus_tcp_demo_cli.h | 42 + .../tcp_utilities/include/tcp_dump_packets.h | 17 +- tools/tcp_utilities/include/tcp_mem_stats.h | 6 +- tools/tcp_utilities/include/tcp_netstat.h | 8 +- tools/tcp_utilities/plus_tcp_demo_cli.c | 1614 +++++++++++++++++ tools/tcp_utilities/tcp_dump_packets.c | 6 +- tools/tcp_utilities/tcp_mem_stats.c | 43 +- tools/tcp_utilities/tcp_netstat.c | 17 +- 16 files changed, 4104 insertions(+), 62 deletions(-) create mode 100644 tools/tcp_utilities/NTPDemo.c create mode 100644 tools/tcp_utilities/date_and_time.c create mode 100644 tools/tcp_utilities/http_client_test.c create mode 100644 tools/tcp_utilities/include/NTPDemo.c create mode 100644 tools/tcp_utilities/include/NTPDemo.h create mode 100644 tools/tcp_utilities/include/date_and_time.h create mode 100644 tools/tcp_utilities/include/http_client_test.h create mode 100644 tools/tcp_utilities/include/ntpClient.h create mode 100644 tools/tcp_utilities/include/plus_tcp_demo_cli.h create mode 100644 tools/tcp_utilities/plus_tcp_demo_cli.c diff --git a/tools/tcp_utilities/NTPDemo.c b/tools/tcp_utilities/NTPDemo.c new file mode 100644 index 0000000000..76d771ee52 --- /dev/null +++ b/tools/tcp_utilities/NTPDemo.c @@ -0,0 +1,693 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + */ + +/* + * NTPDemo.c + * + * An example of how to lookup a domain using DNS + * And also how to send and receive UDP messages to get the NTP time + * + */ + +/* Standard includes. */ +#include +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_DNS.h" +#include "FreeRTOS_Stream_Buffer.h" + +/* Use the date & time functions from +FAT. */ +#if ( USE_PLUS_FAT != 0 ) + #include "ff_time.h" +#endif /* ( USE_PLUS_FAT != 0 ) */ + +#include "NTPDemo.h" +#include "ntpClient.h" + +#include "date_and_time.h" + +#if ( ipconfigDNS_USE_CALLBACKS == 0 ) + #error ipconfigDNS_USE_CALLBACKS must be 1 +#endif + +#if ( ipconfigMULTI_INTERFACE == 0 ) + #ifndef ipSIZE_OF_IPv4_ADDRESS + #define ipSIZE_OF_IPv4_ADDRESS 4 + #endif + #define FREERTOS_AF_INET4 FREERTOS_AF_INET +#endif + +/* Set time: sets the current time in seconds-after-1/1/1970 + * This function must be provided by the application. */ + +time_t get_time( time_t * puxTime ); +int set_time( const time_t * t ); + +enum EStatus +{ + EStatusLookup, + EStatusAsking, + EStatusPause, + EStatusFailed, +}; + +static struct SNtpPacket xNTPPacket; + +BaseType_t xNTPHasTime; +uint32_t ulNTPTime; + +#if ( ipconfigUSE_CALLBACKS == 0 ) + static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ]; +#endif + +static enum EStatus xStatus = EStatusLookup; + +static const char * pcTimeServers[] = +{ + "0.asia.pool.ntp.org", + "0.europe.pool.ntp.org", + "0.id.pool.ntp.org", + "0.south-america.pool.ntp.org", + "0.oceania.pool.ntp.org", + "0.north-america.pool.ntp.org" +}; + +static SemaphoreHandle_t xNTPWakeupSem = NULL; +static uint32_t ulIPAddressFound; + +#if ( ipconfigUSE_IPv6 != 0 ) + static struct freertos_sockaddr6 xIPAddressFound; +#endif +static BaseType_t xHasIPAddress = pdFALSE; + +static Socket_t xNTP_UDPSocket = NULL; +static TaskHandle_t xNTPTaskhandle = NULL; +static TickType_t uxSendTime; +static BaseType_t xPreferredHostType = FREERTOS_AF_INET4; +static BaseType_t xDNSAsynchronous = pdTRUE; +static BaseType_t xDNSLogging = pdFALSE; + +static void prvNTPTask( void * pvParameters ); + +static void vSignalTask( void ) +{ + #if ( ipconfigUSE_CALLBACKS == 0 ) + if( xNTP_UDPSocket != NULL ) + { + /* Send a signal to the socket so that the + * FreeRTOS_recvfrom will get interrupted. */ + FreeRTOS_SignalSocket( xNTP_UDPSocket ); + } + else + #endif + + if( xNTPWakeupSem != NULL ) + { + xSemaphoreGive( xNTPWakeupSem ); + } +} + +void vNTPClearCache( void ) +{ + ulIPAddressFound = 0U; + #if ( ipconfigUSE_IPv6 != 0 ) + { + memset( &( xIPAddressFound ), 0, sizeof xIPAddressFound ); + } + #endif + xHasIPAddress = pdFALSE; +} + +void vNTPSetNTPType( BaseType_t aIPType, + BaseType_t xAsynchronous, + BaseType_t xLogging ) +{ + switch( aIPType ) + { + case 4: + xPreferredHostType = FREERTOS_AF_INET4; + break; + + #if ( ipconfigUSE_IPv6 != 0 ) + case 6: + xPreferredHostType = FREERTOS_AF_INET6; + break; + #endif + default: + break; + } + + xDNSAsynchronous = xAsynchronous; + xDNSLogging = xLogging; + FreeRTOS_printf( ( "NTP config: Using IPv%d, %ssynchronous with%s logging\n", + ( xPreferredHostType == FREERTOS_AF_INET4 ) ? 4 : 6, + xDNSAsynchronous ? "a" : "", + xDNSLogging ? "" : "out" ) ); +} + +BaseType_t xNTPTaskIsRunning() +{ + BaseType_t xResult = ( xNTPTaskhandle != NULL ) ? pdTRUE : pdFALSE; + + return xResult; +} + +void vStartNTPTask( uint16_t usTaskStackSize, + UBaseType_t uxTaskPriority ) +{ + /* The only public function in this module: start a task to contact + * some NTP server. */ + + if( xNTPTaskhandle != NULL ) + { + switch( xStatus ) + { + case EStatusPause: + xStatus = EStatusAsking; + vSignalTask(); + break; + + case EStatusLookup: + FreeRTOS_printf( ( "NTP looking up server\n" ) ); + break; + + case EStatusAsking: + FreeRTOS_printf( ( "NTP still asking\n" ) ); + break; + + case EStatusFailed: + FreeRTOS_printf( ( "NTP failed somehow\n" ) ); + ulIPAddressFound = 0ul; + xStatus = EStatusLookup; + vSignalTask(); + break; + } + } + else + { + xNTP_UDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); + + if( xNTP_UDPSocket != NULL ) + { + struct freertos_sockaddr xAddress; + #if ( ipconfigUSE_CALLBACKS != 0 ) + BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 ); + #else + BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 ); + #endif + + xAddress.sin_addr = 0ul; + xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); + + FreeRTOS_bind( xNTP_UDPSocket, &xAddress, sizeof( xAddress ) ); + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + xTaskCreate( prvNTPTask, /* The function that implements the task. */ + ( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */ + usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ + NULL, /* The task parameter, not used in this case. */ + uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ + &xNTPTaskhandle ); /* The task handle. */ + } + else + { + FreeRTOS_printf( ( "Creating socket failed\n" ) ); + } + } +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_IPv6 != 0 ) + static void vDNS_callback( const char * pcName, + void * pvSearchID, + struct freertos_addrinfo * pxAddress ) + { + ( void ) pvSearchID; + + if( pxAddress == NULL ) + { + FreeRTOS_printf( ( "vDNS_callback: DNS lookup timed out\n" ) ); + } + else + { + if( pxAddress->ai_family == FREERTOS_AF_INET4 ) + { + char pcBuf[ 16 ]; + + /* The DNS lookup has a result, or it has reached the time-out. */ + ulIPAddressFound = pxAddress->ai_addr->sin_addr; + FreeRTOS_inet_ntoa( ulIPAddressFound, pcBuf ); + FreeRTOS_printf( ( "vDNS_callback: IP address of '%s' found: %s\n", pcName, pcBuf ) ); + + if( ulIPAddressFound != 0U ) + { + memset( xIPAddressFound.sin_addr6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS ); + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + } + else if( pxAddress->ai_family == FREERTOS_AF_INET6 ) + { + /* struct freertos_sockaddr * ai_addr */ + struct freertos_sockaddr6 * sockaddr6 = ( struct freertos_sockaddr6 * ) pxAddress->ai_addr; + + xIPAddressFound.sin_len = sizeof( xIPAddressFound ); /* Ignored, still present for backward compatibility. */ + xIPAddressFound.sin_family = FREERTOS_AF_INET6; /* Set to FREERTOS_AF_INET6. */ + xIPAddressFound.sin_port = FreeRTOS_htons( NTP_PORT ); + xIPAddressFound.sin_flowinfo = 0; /* IPv6 flow information. */ + memcpy( xIPAddressFound.sin_addr6.ucBytes, sockaddr6->sin_addr6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); + + FreeRTOS_printf( ( "vDNS_callback: using address %pip\n", xIPAddressFound.sin_addr6.ucBytes ) ); + ulIPAddressFound = 0U; + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + else + { + FreeRTOS_printf( ( "vDNS_callback: Unknown address family 0x%02x\n", ( unsigned ) pxAddress->ai_family ) ); + } + } + + vSignalTask(); + } +#else /* if ( ipconfigUSE_IPv6 != 0 ) */ + static void vDNS_callback( const char * pcName, + void * pvSearchID, + uint32_t ulIPAddress ) + { + char pcBuf[ 16 ]; + + /* The DNS lookup has a result, or it has reached the time-out. */ + FreeRTOS_inet_ntoa( ulIPAddress, pcBuf ); + FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) ); + + if( ulIPAddressFound == 0U ) + { + ulIPAddressFound = ulIPAddress; + } + + /* For testing: in case DNS doesn't respond, still try some NTP server + * with a known IP-address. */ + if( ulIPAddressFound != 0U ) + { + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + + vSignalTask(); + } +#endif /* if ( ipconfigUSE_IPv6 != 0 ) */ +/*-----------------------------------------------------------*/ + +static void prvSwapFields( struct SNtpPacket * pxPacket ) +{ + /* NTP messages are big-endian */ + pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay ); + pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion ); + + pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds ); + pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction ); + + pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds ); + pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction ); + + pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds ); + pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction ); + + pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds ); + pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction ); +} +/*-----------------------------------------------------------*/ + +static void prvNTPPacketInit() +{ + memset( &xNTPPacket, '\0', sizeof( xNTPPacket ) ); + + xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */ + xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */ + xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */ + xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */ + xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */ + + /* use the recorded NTP time */ + time_t uxSecs = get_time( NULL ); /* apTime may be NULL, returns seconds */ + + xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */ + xNTPPacket.transmitTimestamp.seconds = uxSecs + 3; + + /* Transform the contents of the fields from native to big endian. */ + prvSwapFields( &xNTPPacket ); +} +/*-----------------------------------------------------------*/ + +static void prvReadTime( struct SNtpPacket * pxPacket ) +{ + #if ( USE_PLUS_FAT != 0 ) + FF_TimeStruct_t xTimeStruct; + #else + struct tm xTimeStruct; + #endif + + time_t uxPreviousSeconds; + time_t uxPreviousMS; + + time_t uxCurrentSeconds; + time_t uxCurrentMS; + + const char * pcTimeUnit; + int32_t ilDiff; + TickType_t uxTravelTime; + + uxTravelTime = xTaskGetTickCount() - uxSendTime; + + /* Transform the contents of the fields from big to native endian. */ + prvSwapFields( pxPacket ); + + uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970; + uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967; + uxCurrentSeconds += uxCurrentMS / 1000; + uxCurrentMS = uxCurrentMS % 1000; + + /* Get the last time recorded */ + uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS ); + + /* Set the new time with precision in msec. * / */ + FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS ); + + if( uxCurrentSeconds >= uxPreviousSeconds ) + { + ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds ); + } + else + { + ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds ); + } + + if( ( ilDiff < -5 ) || ( ilDiff > 5 ) ) + { + /* More than 5 seconds difference. */ + pcTimeUnit = "sec"; + } + else + { + /* Less than or equal to 5 second difference. */ + pcTimeUnit = "ms"; + uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds; + int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS; + int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS; + ilDiff = iCurMS - iPrevMS; + } + + /*uxCurrentSeconds -= iTimeZone; */ + + #if ( USE_PLUS_FAT != 0 ) + FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct ); + #else + gmtime_r( &uxCurrentSeconds, &xTimeStruct ); + #endif /* ( USE_PLUS_FAT != 0 ) */ + + /* + * 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms) + * 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms) + */ + + FreeRTOS_printf( ( "NTP time: %u/%u/%02u %2u:%02u:%02u.%03u Diff %d %s (%lu ms)\n", + ( unsigned ) xTimeStruct.tm_mday, + ( unsigned ) xTimeStruct.tm_mon + 1, + ( unsigned ) xTimeStruct.tm_year + 1900, + ( unsigned ) xTimeStruct.tm_hour, + ( unsigned ) xTimeStruct.tm_min, + ( unsigned ) xTimeStruct.tm_sec, + ( unsigned ) uxCurrentMS, + ( signed ) ilDiff, + pcTimeUnit, + uxTravelTime ) ); + + xNTPHasTime = pdTRUE; + ulNTPTime = uxCurrentSeconds; + set_time( &uxCurrentSeconds ); + + /* Remove compiler warnings in case FreeRTOS_printf() is not used. */ + ( void ) pcTimeUnit; + ( void ) uxTravelTime; +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_CALLBACKS != 0 ) + + static BaseType_t xOnUDPReceive( Socket_t xSocket, + void * pvData, + size_t xLength, + const struct freertos_sockaddr * pxFrom, + const struct freertos_sockaddr * pxDest ) + { + ( void ) xSocket; + ( void ) pxFrom; + ( void ) pxDest; + + if( xLength >= sizeof( xNTPPacket ) ) + { + prvReadTime( ( struct SNtpPacket * ) pvData ); + + if( xStatus != EStatusPause ) + { + xStatus = EStatusPause; + } + } + + vSignalTask(); + /* Tell the driver not to store the RX data */ + return 1; + } + /*-----------------------------------------------------------*/ + +#endif /* ipconfigUSE_CALLBACKS != 0 */ + +static void prvNTPTask( void * pvParameters ) +{ + BaseType_t xServerIndex = 3; + struct freertos_sockaddr xAddress; + + #if ( ipconfigUSE_CALLBACKS != 0 ) + F_TCP_UDP_Handler_t xHandler; + #endif /* ipconfigUSE_CALLBACKS != 0 */ + + ( void ) pvParameters; + + xStatus = EStatusLookup; + #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 ) + { + xNTPWakeupSem = xSemaphoreCreateBinary(); + } + #endif + + #if ( ipconfigUSE_CALLBACKS != 0 ) + { + memset( &xHandler, '\0', sizeof( xHandler ) ); + xHandler.pxOnUDPReceive = xOnUDPReceive; + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) ); + } + #endif + #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) + { + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) ); + } + #endif + + for( ; ; ) + { + switch( xStatus ) + { + case EStatusLookup: + + if( xHasIPAddress == 0 ) + { + char pcServerName[ 64 ]; + + if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) ) + { + xServerIndex = 0; + } + + snprintf( pcServerName, sizeof pcServerName, "%s", pcTimeServers[ xServerIndex ] ); + + if( ( pcServerName[ 0 ] == '0' ) && ( xPreferredHostType == FREERTOS_AF_INET6 ) ) + { + pcServerName[ 0 ] = '2'; + } + + FreeRTOS_printf( ( "Looking up server '%s' IPv%c\n", + pcServerName, + ( xPreferredHostType == FREERTOS_AF_INET4 ) ? '4' : '6' ) ); + #if ( ipconfigMULTI_INTERFACE != 0 ) + struct freertos_addrinfo xHints; + struct freertos_addrinfo * pxResults = NULL; + + memset( &( xHints ), 0, sizeof xHints ); + xHints.ai_family = xPreferredHostType; + + if( xDNSAsynchronous != 0 ) + { + #if ( ipconfigDNS_USE_CALLBACKS != 0 ) + { + FreeRTOS_getaddrinfo_a( pcServerName, /* The name of the node or device */ + NULL, /* Ignored for now. */ + &( xHints ), /* If not NULL: preferences. */ + &( pxResults ), /* An allocated struct, containing the results. */ + vDNS_callback, + ( void * ) NULL, /* An object or a reference. */ + pdMS_TO_TICKS( 2500U ) ); + } + #else + { + FreeRTOS_printf( ( "ipconfigDNS_USE_CALLBACKS is not defined\n" ) ); + } + #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ + } + else + { + FreeRTOS_getaddrinfo( pcServerName, /* The name of the node or device */ + NULL, /* Ignored for now. */ + &( xHints ), /* If not NULL: preferences. */ + &( pxResults ) ); /* An allocated struct, containing the results. */ + + if( pxResults != NULL ) + { + vDNS_callback( pcServerName, NULL, pxResults ); + } + } + #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */ + #if ( ipconfigDNS_USE_CALLBACKS != 0 ) + FreeRTOS_gethostbyname_a( pcServerName, vDNS_callback, ( void * ) NULL, 1200U ); + #else + uint32_t ulIPAddress = FreeRTOS_gethostbyname( pcServerName ); + + if( ulIPAddress != 0U ) + { + vDNS_callback( pcServerName, NULL, ulIPAddress ); + } + #endif + #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ + } + else + { + xStatus = EStatusAsking; + } + + break; + + case EStatusAsking: + prvNTPPacketInit(); + uxSendTime = xTaskGetTickCount(); + #if ( ipconfigUSE_IPv6 != 0 ) + if( memcmp( xIPAddressFound.sin_addr6.ucBytes, in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) + { + FreeRTOS_printf( ( "Sending UDP message to %pip port %u\n", + xIPAddressFound.sin_addr6.ucBytes, + FreeRTOS_ntohs( xIPAddressFound.sin_port ) ) ); + + FreeRTOS_sendto( xNTP_UDPSocket, + ( void * ) &xNTPPacket, sizeof( xNTPPacket ), + 0, + ( const struct freertos_sockaddr * ) &( xIPAddressFound ), + sizeof( xIPAddressFound ) ); + } + else + #endif /* ( ipconfigUSE_IPv6 != 0 ) */ + { + xAddress.sin_addr = ulIPAddressFound; + xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); + + FreeRTOS_printf( ( "Sending UDP message to %xip port %u\n", + ( unsigned ) FreeRTOS_ntohl( xAddress.sin_addr ), + ( unsigned ) FreeRTOS_ntohs( xAddress.sin_port ) ) ); + + FreeRTOS_sendto( xNTP_UDPSocket, + ( void * ) &xNTPPacket, + sizeof( xNTPPacket ), + 0, &( xAddress ), + sizeof( xAddress ) ); + } + + break; + + case EStatusPause: + break; + + case EStatusFailed: + break; + } + + #if ( ipconfigUSE_CALLBACKS != 0 ) + { + xSemaphoreTake( xNTPWakeupSem, 5000 ); + } + #else + { + uint32_t xAddressSize; + BaseType_t xReturned; + + xAddressSize = sizeof( xAddress ); + xReturned = FreeRTOS_recvfrom( xNTP_UDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize ); + + switch( xReturned ) + { + case 0: + case -pdFREERTOS_ERRNO_EAGAIN: + case -pdFREERTOS_ERRNO_EINTR: + break; + + default: + + if( xReturned < sizeof( xNTPPacket ) ) + { + FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) ); + } + else + { + prvReadTime( ( struct SNtpPacket * ) cRecvBuffer ); + + if( xStatus != EStatusPause ) + { + xStatus = EStatusPause; + } + } + + break; + } + } + #endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */ + } +} +/*-----------------------------------------------------------*/ diff --git a/tools/tcp_utilities/date_and_time.c b/tools/tcp_utilities/date_and_time.c new file mode 100644 index 0000000000..80daee0cbb --- /dev/null +++ b/tools/tcp_utilities/date_and_time.c @@ -0,0 +1,136 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + */ + +#include +#include +#include + +#include "FreeRTOS.h" +#include "task.h" + +#include "date_and_time.h" + +int iTimeZone; + +uint32_t ulSeconds, ulMsec; + +/* + * You can add the following code to you FreeRTOSConfig file: + * + * extern TickType_t ulSeconds, ulMsec; + * + #define traceINCREASE_TICK_COUNT( xTicksToJump ) \ + * { \ + * ulMsec += xTicksToJump; \ + * if( ulMsec >= 1000 ) \ + * { \ + * ulSeconds += ( ulMsec / 1000ul ); \ + * ulMsec = ( ulMsec % 1000ul ); \ + * } \ + * } + * + * + #define traceTASK_INCREMENT_TICK( xTickCount ) \ + * if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) \ + * { \ + * if( ++ulMsec >= 1000 ) \ + * { \ + * ulMsec = 0; \ + * ulSeconds++; \ + * } \ + * } + * + */ + + +time_t FreeRTOS_time( time_t * pxTime ) +{ + time_t uxTime; + + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL(); + { + uxTime = ( time_t ) ulSeconds; + } + portTICK_TYPE_EXIT_CRITICAL(); + + if( pxTime != NULL ) + { + *pxTime = uxTime; + } + + return uxTime; +} +/*-----------------------------------------------------------*/ + +void FreeRTOS_settime( time_t * pxTime ) +{ + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL(); + { + ulSeconds = ( uint32_t ) *pxTime; + ulMsec = ( uint32_t ) 0; + } + portTICK_TYPE_EXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +time_t FreeRTOS_get_secs_msec( time_t * pulMsec ) +{ + time_t uxReturn; + + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL(); + { + uxReturn = ( time_t ) ulSeconds; + + if( pulMsec != NULL ) + { + *pulMsec = ulMsec; + } + } + portTICK_TYPE_EXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + + +void FreeRTOS_set_secs_msec( time_t * pulSeconds, + time_t * pulMsec ) +{ + /* Critical section required if running on a 16 bit processor. */ + portTICK_TYPE_ENTER_CRITICAL(); + { + ulSeconds = *pulSeconds; + + if( pulMsec != NULL ) + { + ulMsec = *pulMsec; + } + } + portTICK_TYPE_EXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ diff --git a/tools/tcp_utilities/http_client_test.c b/tools/tcp_utilities/http_client_test.c new file mode 100644 index 0000000000..4e2e17d153 --- /dev/null +++ b/tools/tcp_utilities/http_client_test.c @@ -0,0 +1,616 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 http_client.c + * @brief Implements the Domain Name System for the FreeRTOS+TCP network stack. + */ + +/* Standard includes. */ +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_DNS.h" +#if ( ipconfigMULTI_INTERFACE != 0 ) + #include "FreeRTOS_Routing.h" +#endif + +#include "http_client_test.h" + +/* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */ +#if ( ipconfigUSE_TCP == 1 ) + + #ifndef echoNUM_HTTP_CLIENTS + /* The number of instances of the echo client task to create. */ + #define echoNUM_HTTP_CLIENTS ( 2 ) + #endif + + #ifndef httpREMOTE_FILENAME + #define httpREMOTE_FILENAME "/index.html" + #endif + +/* The echo tasks create a socket, send out a number of echo requests, listen + * for the echo reply, then close the socket again before starting over. This + * delay is used between each iteration to ensure the network does not get too + * congested. */ + #define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS ) + +/* The echo server is assumed to be on port 7, which is the standard echo + * protocol port. */ + + #define echoECHO_PORT ( 80 ) + +/* If ipconfigUSE_TCP_WIN is 1 then the Tx socket will use a buffer size set by + * ipconfigTCP_TX_BUF_LEN, and the Tx window size will be + * configECHO_CLIENT_TX_WINDOW_SIZE times the buffer size. Note + * ipconfigTCP_TX_BUF_LEN is set in FreeRTOSIPConfig.h as it is a standard TCP/IP + * stack constant, whereas configECHO_CLIENT_TX_WINDOW_SIZE is set in + * FreeRTOSConfig.h as it is a demo application constant. */ + #ifndef configECHO_CLIENT_TX_WINDOW_SIZE + #define configECHO_CLIENT_TX_WINDOW_SIZE 2 + #endif + +/* If ipconfigUSE_TCP_WIN is 1 then the Rx socket will use a buffer size set by + * ipconfigTCP_RX_BUFFER_LENGTH, and the Rx window size will be + * configECHO_CLIENT_RX_WINDOW_SIZE times the buffer size. Note + * ipconfigTCP_RX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP + * stack constant, whereas configECHO_CLIENT_RX_WINDOW_SIZE is set in + * FreeRTOSConfig.h as it is a demo application constant. */ + #ifndef configECHO_CLIENT_RX_WINDOW_SIZE + #define configECHO_CLIENT_RX_WINDOW_SIZE 2 + #endif + + static uint16_t usUsePortNumber = echoECHO_PORT; + +/*2404:6800:4003:c02::5e */ +/*66.96.149.18 */ +/*-----------------------------------------------------------*/ + +/* + * Uses a socket to send data to, then receive data from, the standard echo + * port number 7. + */ + static void prvEchoClientTask( void * pvParameters ); + + void printBuffer( const char * apBuffer, + int aLen, + int aLineLen, + const char * apPrefix ); + +/*-----------------------------------------------------------*/ + +/* Counters for each created task - for inspection only. */ + static uint32_t ulTxRxCycles[ echoNUM_HTTP_CLIENTS ] = { 0 }, + ulConnections[ echoNUM_HTTP_CLIENTS ] = { 0 }, + xIPVersion[ echoNUM_HTTP_CLIENTS ] = { 0 }; + + static TaskHandle_t xSocketTaskHandles[ echoNUM_HTTP_CLIENTS ]; + +/* When element is non-zero, the corresponding task may run. */ + static BaseType_t xAllowedToStart[ echoNUM_HTTP_CLIENTS ] = { 0 }; + +/* Each task connects to its own host. */ + static char pcHostNames[ echoNUM_HTTP_CLIENTS ][ ipconfigDNS_CACHE_NAME_LENGTH ]; + +/* Each task retrieves its own file. */ + static char pcFileNames[ echoNUM_HTTP_CLIENTS ][ ipconfigDNS_CACHE_NAME_LENGTH ]; + + const char get_command[] = + "GET %s HTTP/1.1\x0d\x0a" + "Host: %s\x0d\x0a" + "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0\x0d\x0a" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\x0d\x0a" + "Accept-Language: en-US,en;q=0.5\x0d\x0a" + "DNT: 1\x0d\x0a" + "Connection: keep-alive\x0d\x0a" + "Upgrade-Insecure-Requests: 1\x0d\x0a" + "If-Modified-Since: Fri, 16 Aug 2019 05:18:19 GMT\x0d\x0a" + "\x0d\x0a"; + +/*-----------------------------------------------------------*/ + + void vStartHTTPClientTest( uint16_t usTaskStackSize, + UBaseType_t uxTaskPriority ) + { + BaseType_t x; + static char pcNames[ echoNUM_HTTP_CLIENTS ][ configMAX_TASK_NAME_LEN + 1 ]; + static BaseType_t xHasStarted = pdFALSE; + + if( xHasStarted == pdFALSE ) + { + xHasStarted = pdTRUE; + + /* Create the echo client tasks. */ + for( x = 0; x < echoNUM_HTTP_CLIENTS; x++ ) + { + snprintf( pcNames[ x ], sizeof pcNames[ x ], "Client_%ld", x ); + xTaskCreate( prvEchoClientTask, /* The function that implements the task. */ + pcNames[ x ], /* Just a text name for the task to aid debugging. */ + usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ + ( void * ) x, /* The task parameter, not used in this case. */ + uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ + &( xSocketTaskHandles[ x ] ) ); /* Remember the handle. */ + } + } + } +/*-----------------------------------------------------------*/ + +/** + * @brief Wake-up a HTTP client task. aIndex + * @param[in] uxIndex: the task number ( 0 .. echoNUM_HTTP_CLIENTS-1 ). + * @param[in] pcHost: the name of the host from which to download index.html + */ + void wakeupHTTPClient( size_t uxIndex, + const char * pcHost, + const char * pcFileName, + uint16_t usPortNumber, + BaseType_t xIPType ) + { + if( ( uxIndex < echoNUM_HTTP_CLIENTS ) && ( xSocketTaskHandles[ uxIndex ] != NULL ) ) + { + xIPVersion[ uxIndex ] = xIPType; + usUsePortNumber = usPortNumber; + snprintf( pcHostNames[ uxIndex ], sizeof pcHostNames[ uxIndex ], "%s", pcHost ); + + if( ( pcFileName != NULL ) && ( pcFileName[ 0 ] != 0 ) ) + { + snprintf( pcFileNames[ uxIndex ], sizeof( pcFileNames[ uxIndex ] ), pcFileName ); + } + else + { + snprintf( pcFileNames[ uxIndex ], sizeof( pcFileNames[ uxIndex ] ), httpREMOTE_FILENAME ); + } + + xAllowedToStart[ uxIndex ]++; + xTaskNotifyGive( xSocketTaskHandles[ uxIndex ] ); + } + } + +/** + * @brief Wake-up a HTTP client task. aIndex + * @param[in] pvParameters: the task number as a void pointer. + */ + static void prvEchoClientTask( void * pvParameters ) + { + Socket_t xSocket = NULL; + + #if ( ipconfigUSE_IPv6 != 0 ) + struct freertos_sockaddr6 xEchoServerAddress; + #else + struct freertos_sockaddr xEchoServerAddress; + #endif + + size_t uxInstance; + int32_t xReturned, xReceivedBytes; + BaseType_t lTransmitted; + TickType_t xTimeOnEntering; + + #if ( ipconfigUSE_TCP_WIN == 1 ) + WinProperties_t xWinProps; + + /* Fill in the buffer and window sizes that will be used by the socket. */ + xWinProps.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH; + xWinProps.lTxWinSize = configECHO_CLIENT_TX_WINDOW_SIZE; + xWinProps.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH; + xWinProps.lRxWinSize = configECHO_CLIENT_RX_WINDOW_SIZE; + #endif /* ipconfigUSE_TCP_WIN */ + + #if ( ipconfigUSE_IPv6 != 0 ) + struct freertos_sockaddr * pxAddress = ( struct freertos_sockaddr * ) &xEchoServerAddress; + #else + struct freertos_sockaddr * pxAddress = &xEchoServerAddress; + #endif + + /* This task can be created a number of times. Each instance is numbered + * to enable each instance to use a different Rx and Tx buffer. The number is + * passed in as the task's parameter. */ + { + /* A two-step assignment. */ + intptr_t uxIntPtr = ( intptr_t ) pvParameters; + uxInstance = ( size_t ) uxIntPtr; + configASSERT( uxInstance < echoNUM_HTTP_CLIENTS ); + } + + if( uxInstance < echoNUM_HTTP_CLIENTS ) + { + xSocketTaskHandles[ uxInstance ] = xTaskGetCurrentTaskHandle(); + } + + for( ; ; ) + { + int rc; + struct freertos_sockaddr xBindAddress; + const char * pcHostname; + uint32_t ulIPAddress = 0U; + BaseType_t xHasIPv6Address = pdFALSE; + char pcBuffer[ 512 ]; + + /* Rx and Tx time outs are used to ensure the sockets do not wait too long for + * missing data. */ + TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 2500U ); + TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000U ); + #if ( ipconfigUSE_IPv6 != 0 ) + IPv6_Address_t xIPAddress_IPv6; + struct freertos_sockaddr6 xLocalAddress; + #else + struct freertos_sockaddr xLocalAddress; + #endif + #if ( ipconfigMULTI_INTERFACE != 0 ) + struct freertos_addrinfo * pxResult = NULL; + struct freertos_addrinfo xHints; + NetworkEndPoint_t * pxEndPoint; + #endif + + if( xSocketValid( xSocket ) == pdTRUE ) + { + FreeRTOS_closesocket( xSocket ); + } + + xSocket = NULL; + + while( xAllowedToStart[ uxInstance ] == 0 ) + { + ulTaskNotifyTake( pdTRUE, 100 ); + } + + xAllowedToStart[ uxInstance ] = 0; + + #if ( ipconfigMULTI_INTERFACE != 0 ) + if( xIPVersion[ uxInstance ] != 6 ) + { + xHints.ai_family = FREERTOS_AF_INET; + } + else + { + xHints.ai_family = FREERTOS_AF_INET6; + } + #endif + pcHostname = pcHostNames[ uxInstance ]; + + { + #if ( ipconfigMULTI_INTERFACE == 0 ) + ulIPAddress = FreeRTOS_gethostbyname( pcHostname ); + + if( ulIPAddress == 0U ) + { + continue; + } + #else + pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv4 ); + + if( ( pxEndPoint != NULL ) && ( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) ) + { + xARPWaitResolution( pxEndPoint->ipv4_settings.ulGatewayAddress, pdMS_TO_TICKS( 1000U ) ); + } + + BaseType_t rc_dns = FreeRTOS_getaddrinfo( + pcHostname, /* The node. */ + NULL, /* const char *pcService: ignored for now. */ + &xHints, /* If not NULL: preferences. */ + &pxResult ); /* An allocated struct, containing the results. */ + FreeRTOS_printf( ( "httpTest: FreeRTOS_getaddrinfo: rc %d\n", ( int ) rc_dns ) ); + + if( ( rc_dns != 0 ) || ( pxResult == NULL ) ) + { + continue; + } + + if( pxResult->ai_family == FREERTOS_AF_INET4 ) + { +/* ulIPAddress = ( ( struct freertos_sockaddr * ) pxResult->ai_addr )->sin_addr; */ + ulIPAddress = pxResult->ai_addr->sin_addr; + } + + #if ( ipconfigUSE_IPv6 != 0 ) + else if( pxResult->ai_family == FREERTOS_AF_INET6 ) + { + struct freertos_sockaddr6 * pxAddr6; + + pxAddr6 = ( struct freertos_sockaddr6 * ) pxResult->ai_addr; + memcpy( xIPAddress_IPv6.ucBytes, pxAddr6->sin_addr6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); + xHasIPv6Address = pdTRUE; + } + #endif + else + { + continue; + } + #endif /* if ( ipconfigMULTI_INTERFACE == 0 ) */ + } + + #if ( ipconfigUSE_IPv6 != 0 ) + if( xHasIPv6Address != 0 ) + { + xEchoServerAddress.sin_len = sizeof( struct freertos_sockaddr6 ); + xEchoServerAddress.sin_family = FREERTOS_AF_INET6; + xEchoServerAddress.sin_port = FreeRTOS_htons( usUsePortNumber ); + memcpy( xEchoServerAddress.sin_addr6.ucBytes, xIPAddress_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); + } + else + #endif + + if( ulIPAddress != 0U ) + { + pxAddress->sin_len = sizeof( struct freertos_sockaddr ); + pxAddress->sin_family = FREERTOS_AF_INET; + pxAddress->sin_port = FreeRTOS_htons( usUsePortNumber ); + pxAddress->sin_addr = ulIPAddress; + } + else + { + configASSERT( 0 == 1 ); + } + + /* Create a TCP socket. */ + xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP ); + configASSERT( xSocketValid( xSocket ) == pdTRUE ); + + memset( &( xBindAddress ), 0, sizeof( xBindAddress ) ); + + #if ( ipconfigMULTI_INTERFACE != 0 ) + #if ( ipconfigUSE_IPv6 != 0 ) + if( xEchoServerAddress.sin_family == FREERTOS_AF_INET6 ) + { + pxEndPoint = FreeRTOS_FindEndPointOnNetMask_IPv6( &( xEchoServerAddress.sin_addr6 ) ); + + if( pxEndPoint == NULL ) + { + pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv6 ); + } + + if( pxEndPoint != NULL ) + { + /*memcpy( xEchoServerAddress.sin_addr6.ucBytes, pxEndPoint->ipv6.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); */ + } + } + else + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + { + pxEndPoint = FreeRTOS_FindEndPointOnNetMask( pxAddress->sin_addr, 9999 ); + + if( pxEndPoint != NULL ) + { + xBindAddress.sin_addr = pxEndPoint->ipv4_settings.ulIPAddress; + } + } + #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ + rc = FreeRTOS_bind( xSocket, &( xBindAddress ), sizeof( xBindAddress ) ); + + if( rc != 0 ) + { + FreeRTOS_printf( ( "httpTest: bind fails with errno %d\n", rc ) ); + configASSERT( rc == 0 ); + } + + /* Set a time out so a missing reply does not cause the task to block + * indefinitely. */ + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) ); + + #if ( ipconfigUSE_TCP_WIN == 1 ) + { + /* Set the window and buffer sizes. */ + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) ); + } + #endif /* ipconfigUSE_TCP_WIN */ + + FreeRTOS_GetLocalAddress( xSocket, &xLocalAddress ); + /* Connect to the echo server. */ + rc = FreeRTOS_connect( xSocket, ( struct freertos_sockaddr * ) &xEchoServerAddress, sizeof( xEchoServerAddress ) ); + + #if ( ipconfigUSE_IPv6 != 0 ) + struct freertos_sockaddr * pxLocalAddress = ( struct freertos_sockaddr * ) &xLocalAddress; + #else + struct freertos_sockaddr * pxLocalAddress = &xLocalAddress; + #endif + + #if ( ipconfigUSE_IPv6 != 0 ) + if( pxAddress->sin_family == FREERTOS_AF_INET6 ) + { + FreeRTOS_printf( ( "httpTest: FreeRTOS_connect to %pip port %u: rc %d\n", + xEchoServerAddress.sin_addr6.ucBytes, + FreeRTOS_ntohs( pxAddress->sin_port ), + rc ) ); + } + else + #endif + { + FreeRTOS_printf( ( "httpTest: FreeRTOS_connect from %lxip port %u to %lxip port %u: rc %d\n", + FreeRTOS_ntohl( pxLocalAddress->sin_addr ), + FreeRTOS_ntohs( pxLocalAddress->sin_port ), + FreeRTOS_ntohl( pxAddress->sin_addr ), + FreeRTOS_ntohs( pxAddress->sin_port ), + rc ) ); + } + + if( rc == 0 ) + { + ulConnections[ uxInstance ]++; + + /* Send a HTTP request. */ + { + BaseType_t xLoop; + size_t uxLength; + /* Send the string to the socket. */ + uxLength = snprintf( pcBuffer, sizeof( pcBuffer ), get_command, pcFileNames[ uxInstance ], pcHostname ); + lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */ + ( void * ) pcBuffer, /* The data being sent. */ + uxLength, /* The length of the data being sent. */ + 0 ); /* No flags. */ + FreeRTOS_printf( ( "httpTest: FreeRTOS_send : rc %ld\n", lTransmitted ) ); + + if( lTransmitted < 0 ) + { + /* Error? */ + break; + } + + /* Clear the buffer into which the echoed string will be + * placed. */ + memset( ( void * ) pcBuffer, 0x00, sizeof( pcBuffer ) ); + xReceivedBytes = 0; + + /* Receive data echoed back to the socket. */ + for( xLoop = 0; xLoop < 10; xLoop++ ) + { + xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ + pcBuffer, /* The buffer into which the received data will be written. */ + sizeof( pcBuffer ), /* The size of the buffer provided to receive the data. */ + 0 ); /* No flags. */ + + FreeRTOS_printf( ( "httpTest: FreeRTOS_recv : rc %ld\n", xReturned ) ); + + if( xReturned < 0 ) + { + /* Error occurred. Latch it so it can be detected + * below. */ + xReceivedBytes = xReturned; + break; + } + else if( xReturned == 0 ) + { + /* Timed out. */ + break; + } + else + { + /* Use a short RX time-out the next time. */ + xReceiveTimeOut = pdMS_TO_TICKS( 500U ); + FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + /* Keep a count of the bytes received so far. */ + xReceivedBytes += xReturned; + printBuffer( pcBuffer, xReturned, 129, "" ); + } + } /* for( xLoop = 0; xLoop < 10; xLoop++ ) */ + } + + /* Finished using the connected socket, initiate a graceful close: + * FIN, FIN+ACK, ACK. */ + FreeRTOS_printf( ( "httpTest: prvEchoClientTask: shut down connection\n" ) ); + FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR ); + + /* Expect FreeRTOS_recv() to return an error once the shutdown is + * complete. */ + xTimeOnEntering = xTaskGetTickCount(); + + do + { + xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ + pcBuffer, /* The buffer into which the received data will be written. */ + sizeof( pcBuffer ), /* The size of the buffer provided to receive the data. */ + 0 ); + + if( xReturned < 0 ) + { + break; + } + } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut ); + + FreeRTOS_printf( ( "httpTest: connection is down\n" ) ); + } + + /* Close this socket before looping back to create another. */ + FreeRTOS_closesocket( xSocket ); + xSocket = NULL; + FreeRTOS_printf( ( "httpTest: test is ready\n" ) ); + + /* Pause for a short while to ensure the network is not too + * congested. */ +/* vTaskDelay( echoLOOP_DELAY ); */ + } + } +/*-----------------------------------------------------------*/ + + void printBuffer( const char * apBuffer, + int aLen, + int aLineLen, + const char * apPrefix ) + { + const char * ptr = apBuffer; + const char * end = apBuffer + aLen; + + for( ; ; ) + { + const char * next = ptr; + const char * eot; + + /* Find the first null, newline of end of text. */ + for( ; ; ) + { + if( ( next >= end ) || ( *next == '\0' ) ) + { + eot = next; + next = NULL; + break; + } + + if( ( *next == '\n' ) || ( *next == '\r' ) ) + { + char eol = *next == '\n' ? '\r' : '\n'; + eot = next; + + do + { + next++; + } while( *next == eol ); + + break; + } + + if( ( int ) ( next - ptr ) >= aLineLen ) + { + eot = next; + break; + } + + next++; + } + + { + char save = *eot; + *( ( char * ) eot ) = '\0'; + FreeRTOS_printf( ( "%s%s\n", apPrefix, ptr ) ); + *( ( char * ) eot ) = save; + } + + if( next == NULL ) + { + break; + } + + ptr = next; + } + } + +#endif /* ipconfigUSE_TCP */ diff --git a/tools/tcp_utilities/include/NTPDemo.c b/tools/tcp_utilities/include/NTPDemo.c new file mode 100644 index 0000000000..13dfbdf382 --- /dev/null +++ b/tools/tcp_utilities/include/NTPDemo.c @@ -0,0 +1,693 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + */ + +/* + * NTPDemo.c + * + * An example of how to lookup a domain using DNS + * And also how to send and receive UDP messages to get the NTP time + * + */ + +/* Standard includes. */ +#include +#include +#include +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "FreeRTOS_DNS.h" +#include "FreeRTOS_Stream_Buffer.h" + +/* Use the date & time functions from +FAT. */ +#if ( USE_PLUS_FAT != 0 ) + #include "ff_time.h" +#endif /* ( USE_PLUS_FAT != 0 ) */ + +#include "NTPDemo.h" +#include "ntpClient.h" + +#include "date_and_time.h" + +#if ( ipconfigDNS_USE_CALLBACKS == 0 ) + #error ipconfigDNS_USE_CALLBACKS must be 1 +#endif + +#if ( ipconfigMULTI_INTERFACE == 0 ) + #ifndef ipSIZE_OF_IPv4_ADDRESS + #define ipSIZE_OF_IPv4_ADDRESS 4 + #endif + #define FREERTOS_AF_INET4 FREERTOS_AF_INET +#endif + +/* Set time: sets the current time in seconds-after-1/1/1970 + * This function must be provided by the application. */ + +time_t get_time( time_t * puxTime ); +int set_time( const time_t * t ); + +enum EStatus +{ + EStatusLookup, + EStatusAsking, + EStatusPause, + EStatusFailed, +}; + +static struct SNtpPacket xNTPPacket; + +BaseType_t xNTPHasTime; +uint32_t ulNTPTime; + +#if ( ipconfigUSE_CALLBACKS == 0 ) + static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ]; +#endif + +static enum EStatus xStatus = EStatusLookup; + +static const char * pcTimeServers[] = +{ + "0.asia.pool.ntp.org", + "0.europe.pool.ntp.org", + "0.id.pool.ntp.org", + "0.south-america.pool.ntp.org", + "0.oceania.pool.ntp.org", + "0.north-america.pool.ntp.org" +}; + +static SemaphoreHandle_t xNTPWakeupSem = NULL; +static uint32_t ulIPAddressFound; + +#if ( ipconfigUSE_IPv6 != 0 ) + static struct freertos_sockaddr6 xIPAddressFound; +#endif +static BaseType_t xHasIPAddress = pdFALSE; + +static Socket_t xNTP_UDPSocket = NULL; +static TaskHandle_t xNTPTaskhandle = NULL; +static TickType_t uxSendTime; +static BaseType_t xPreferredHostType = FREERTOS_AF_INET4; +static BaseType_t xDNSAsynchronous = pdTRUE; +static BaseType_t xDNSLogging = pdFALSE; + +static void prvNTPTask( void * pvParameters ); + +static void vSignalTask( void ) +{ + #if ( ipconfigUSE_CALLBACKS == 0 ) + if( xNTP_UDPSocket != NULL ) + { + /* Send a signal to the socket so that the + * FreeRTOS_recvfrom will get interrupted. */ + FreeRTOS_SignalSocket( xNTP_UDPSocket ); + } + else + #endif + + if( xNTPWakeupSem != NULL ) + { + xSemaphoreGive( xNTPWakeupSem ); + } +} + +void vNTPClearCache( void ) +{ + ulIPAddressFound = 0U; + #if ( ipconfigUSE_IPv6 != 0 ) + { + memset( &( xIPAddressFound ), 0, sizeof xIPAddressFound ); + } + #endif + xHasIPAddress = pdFALSE; +} + +void vNTPSetNTPType( BaseType_t aIPType, + BaseType_t xAsynchronous, + BaseType_t xLogging ) +{ + switch( aIPType ) + { + case 4: + xPreferredHostType = FREERTOS_AF_INET4; + break; + + #if ( ipconfigUSE_IPv6 != 0 ) + case 6: + xPreferredHostType = FREERTOS_AF_INET6; + break; + #endif + default: + break; + } + + xDNSAsynchronous = xAsynchronous; + xDNSLogging = xLogging; + FreeRTOS_printf( ( "NTP config: Using IPv%d, %ssynchronous with%s logging\n", + ( xPreferredHostType == FREERTOS_AF_INET4 ) ? 4 : 6, + xDNSAsynchronous ? "a" : "", + xDNSLogging ? "" : "out" ) ); +} + +BaseType_t xNTPTaskIsRunning() +{ + BaseType_t xResult = ( xNTPTaskhandle != NULL ) ? pdTRUE : pdFALSE; + + return xResult; +} + +void vStartNTPTask( uint16_t usTaskStackSize, + UBaseType_t uxTaskPriority ) +{ + /* The only public function in this module: start a task to contact + * some NTP server. */ + + if( xNTPTaskhandle != NULL ) + { + switch( xStatus ) + { + case EStatusPause: + xStatus = EStatusAsking; + vSignalTask(); + break; + + case EStatusLookup: + FreeRTOS_printf( ( "NTP looking up server\n" ) ); + break; + + case EStatusAsking: + FreeRTOS_printf( ( "NTP still asking\n" ) ); + break; + + case EStatusFailed: + FreeRTOS_printf( ( "NTP failed somehow\n" ) ); + ulIPAddressFound = 0ul; + xStatus = EStatusLookup; + vSignalTask(); + break; + } + } + else + { + xNTP_UDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); + + if( xNTP_UDPSocket != NULL ) + { + struct freertos_sockaddr xAddress; + #if ( ipconfigUSE_CALLBACKS != 0 ) + BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 ); + #else + BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 ); + #endif + + xAddress.sin_addr = 0ul; + xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); + + FreeRTOS_bind( xNTP_UDPSocket, &xAddress, sizeof( xAddress ) ); + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); + xTaskCreate( prvNTPTask, /* The function that implements the task. */ + ( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */ + usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ + NULL, /* The task parameter, not used in this case. */ + uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ + &xNTPTaskhandle ); /* The task handle. */ + } + else + { + FreeRTOS_printf( ( "Creating socket failed\n" ) ); + } + } +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_IPv6 != 0 ) + static void vDNS_callback( const char * pcName, + void * pvSearchID, + struct freertos_addrinfo * pxAddress ) + { + ( void ) pvSearchID; + + if( pxAddress == NULL ) + { + FreeRTOS_printf( ( "vDNS_callback: DNS lookup timed out\n" ) ); + } + else + { + if( pxAddress->ai_family == FREERTOS_AF_INET4 ) + { + char pcBuf[ 16 ]; + + /* The DNS lookup has a result, or it has reached the time-out. */ + ulIPAddressFound = pxAddress->ai_addr->sin_addr; + FreeRTOS_inet_ntoa( ulIPAddressFound, pcBuf ); + FreeRTOS_printf( ( "vDNS_callback: IP address of '%s' found: %s\n", pcName, pcBuf ) ); + + if( ulIPAddressFound != 0U ) + { + memset( xIPAddressFound.sin_addr6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS ); + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + } + else if( pxAddress->ai_family == FREERTOS_AF_INET6 ) + { + /* struct freertos_sockaddr * ai_addr */ + struct freertos_sockaddr6 * sockaddr6 = ( struct freertos_sockaddr6 * ) pxAddress->ai_addr; + + xIPAddressFound.sin_len = sizeof( xIPAddressFound ); /* Ignored, still present for backward compatibility. */ + xIPAddressFound.sin_family = FREERTOS_AF_INET6; /* Set to FREERTOS_AF_INET6. */ + xIPAddressFound.sin_port = FreeRTOS_htons( NTP_PORT ); + xIPAddressFound.sin_flowinfo = 0; /* IPv6 flow information. */ + memcpy( xIPAddressFound.sin_addr6.ucBytes, sockaddr6->sin_addr6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); + + FreeRTOS_printf( ( "vDNS_callback: using address %pip\n", xIPAddressFound.sin_addr6.ucBytes ) ); + ulIPAddressFound = 0U; + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + else + { + FreeRTOS_printf( ( "vDNS_callback: Unknown address family 0x%02x\n", ( unsigned ) pxAddress->ai_family ) ); + } + } + + vSignalTask(); + } +#else /* if ( ipconfigUSE_IPv6 != 0 ) */ + static void vDNS_callback( const char * pcName, + void * pvSearchID, + uint32_t ulIPAddress ) + { + char pcBuf[ 16 ]; + + /* The DNS lookup has a result, or it has reached the time-out. */ + FreeRTOS_inet_ntoa( ulIPAddress, pcBuf ); + FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) ); + + if( ulIPAddressFound == 0U ) + { + ulIPAddressFound = ulIPAddress; + } + + /* For testing: in case DNS doesn't respond, still try some NTP server + * with a known IP-address. */ + if( ulIPAddressFound != 0U ) + { + xHasIPAddress = pdTRUE; + xStatus = EStatusAsking; + } + + vSignalTask(); + } +#endif /* if ( ipconfigUSE_IPv6 != 0 ) */ +/*-----------------------------------------------------------*/ + +static void prvSwapFields( struct SNtpPacket * pxPacket ) +{ + /* NTP messages are big-endian */ + pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay ); + pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion ); + + pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds ); + pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction ); + + pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds ); + pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction ); + + pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds ); + pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction ); + + pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds ); + pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction ); +} +/*-----------------------------------------------------------*/ + +static void prvNTPPacketInit() +{ + memset( &xNTPPacket, '\0', sizeof( xNTPPacket ) ); + + xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */ + xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */ + xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */ + xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */ + xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */ + + /* use the recorded NTP time */ + time_t uxSecs = get_time( NULL ); /* apTime may be NULL, returns seconds */ + + xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */ + xNTPPacket.transmitTimestamp.seconds = uxSecs + 3; + + /* Transform the contents of the fields from native to big endian. */ + prvSwapFields( &xNTPPacket ); +} +/*-----------------------------------------------------------*/ + +static void prvReadTime( struct SNtpPacket * pxPacket ) +{ + #if ( USE_PLUS_FAT != 0 ) + FF_TimeStruct_t xTimeStruct; + #else + struct tm xTimeStruct; + #endif + + time_t uxPreviousSeconds; + time_t uxPreviousMS; + + time_t uxCurrentSeconds; + time_t uxCurrentMS; + + const char * pcTimeUnit; + int32_t ilDiff; + TickType_t uxTravelTime; + + uxTravelTime = xTaskGetTickCount() - uxSendTime; + + /* Transform the contents of the fields from big to native endian. */ + prvSwapFields( pxPacket ); + + uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970; + uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967; + uxCurrentSeconds += uxCurrentMS / 1000; + uxCurrentMS = uxCurrentMS % 1000; + + /* Get the last time recorded */ + uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS ); + + /* Set the new time with precision in msec. * / */ + FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS ); + + if( uxCurrentSeconds >= uxPreviousSeconds ) + { + ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds ); + } + else + { + ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds ); + } + + if( ( ilDiff < -5 ) || ( ilDiff > 5 ) ) + { + /* More than 5 seconds difference. */ + pcTimeUnit = "sec"; + } + else + { + /* Less than or equal to 5 second difference. */ + pcTimeUnit = "ms"; + uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds; + int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS; + int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS; + ilDiff = iCurMS - iPrevMS; + } + + /*uxCurrentSeconds -= iTimeZone; */ + + #if ( USE_PLUS_FAT != 0 ) + FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct ); + #else + gmtime_r( &uxCurrentSeconds, &xTimeStruct ); + #endif /* ( USE_PLUS_FAT != 0 ) */ + + /* + * 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms) + * 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms) + */ + + FreeRTOS_printf( ( "NTP time: %u/%u/%02u %2u:%02u:%02u.%03u Diff %d %s (%lu ms)\n", + ( unsigned ) xTimeStruct.tm_mday, + ( unsigned ) xTimeStruct.tm_mon + 1, + ( unsigned ) xTimeStruct.tm_year + 1900, + ( unsigned ) xTimeStruct.tm_hour, + ( unsigned ) xTimeStruct.tm_min, + ( unsigned ) xTimeStruct.tm_sec, + ( unsigned ) uxCurrentMS, + ( signed ) ilDiff, + pcTimeUnit, + uxTravelTime ) ); + + xNTPHasTime = pdTRUE; + ulNTPTime = uxCurrentSeconds; + set_time( &uxCurrentSeconds ); + + /* Remove compiler warnings in case FreeRTOS_printf() is not used. */ + ( void ) pcTimeUnit; + ( void ) uxTravelTime; +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_CALLBACKS != 0 ) + + static BaseType_t xOnUDPReceive( Socket_t xSocket, + void * pvData, + size_t xLength, + const struct freertos_sockaddr * pxFrom, + const struct freertos_sockaddr * pxDest ) + { + ( void ) xSocket; + ( void ) pxFrom; + ( void ) pxDest; + + if( xLength >= sizeof( xNTPPacket ) ) + { + prvReadTime( ( struct SNtpPacket * ) pvData ); + + if( xStatus != EStatusPause ) + { + xStatus = EStatusPause; + } + } + + vSignalTask(); + /* Tell the driver not to store the RX data */ + return 1; + } + /*-----------------------------------------------------------*/ + +#endif /* ipconfigUSE_CALLBACKS != 0 */ + +static void prvNTPTask( void * pvParameters ) +{ + BaseType_t xServerIndex = 3; + struct freertos_sockaddr xAddress; + + #if ( ipconfigUSE_CALLBACKS != 0 ) + F_TCP_UDP_Handler_t xHandler; + #endif /* ipconfigUSE_CALLBACKS != 0 */ + + ( void ) pvParameters; + + xStatus = EStatusLookup; + #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 ) + { + xNTPWakeupSem = xSemaphoreCreateBinary(); + } + #endif + + #if ( ipconfigUSE_CALLBACKS != 0 ) + { + memset( &xHandler, '\0', sizeof( xHandler ) ); + xHandler.pxOnUDPReceive = xOnUDPReceive; + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) ); + } + #endif + #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) + { + FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) ); + } + #endif + + for( ; ; ) + { + switch( xStatus ) + { + case EStatusLookup: + + if( xHasIPAddress == 0 ) + { + char pcServerName[ 64 ]; + + if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) ) + { + xServerIndex = 0; + } + + snprintf( pcServerName, sizeof pcServerName, "%s", pcTimeServers[ xServerIndex ] ); + + if( ( pcServerName[ 0 ] == '0' ) && ( xPreferredHostType == FREERTOS_AF_INET6 ) ) + { + pcServerName[ 0 ] = '2'; + } + + FreeRTOS_printf( ( "Looking up server '%s' IPv%c\n", + pcServerName, + ( xPreferredHostType == FREERTOS_AF_INET4 ) ? '4' : '6' ) ); + #if ( ipconfigMULTI_INTERFACE != 0 ) + struct freertos_addrinfo xHints; + struct freertos_addrinfo * pxResults = NULL; + + memset( &( xHints ), 0, sizeof xHints ); + xHints.ai_family = xPreferredHostType; + + if( xDNSAsynchronous != 0 ) + { + #if ( ipconfigDNS_USE_CALLBACKS != 0 ) + { + FreeRTOS_getaddrinfo_a( pcServerName, /* The name of the node or device */ + NULL, /* Ignored for now. */ + &( xHints ), /* If not NULL: preferences. */ + &( pxResults ), /* An allocated struct, containing the results. */ + vDNS_callback, + ( void * ) NULL, /* An object or a reference. */ + pdMS_TO_TICKS( 2500U ) ); + } + #else + { + FreeRTOS_printf( ( "ipconfigDNS_USE_CALLBACKS is not defined\n" ) ); + } + #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ + } + else + { + FreeRTOS_getaddrinfo( pcServerName, /* The name of the node or device */ + NULL, /* Ignored for now. */ + &( xHints ), /* If not NULL: preferences. */ + &( pxResults ) ); /* An allocated struct, containing the results. */ + + if( pxResults != NULL ) + { + vDNS_callback( pcServerName, NULL, pxResults ); + } + } + #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */ + #if ( ipconfigDNS_USE_CALLBACKS != 0 ) + FreeRTOS_gethostbyname_a( pcServerName, vDNS_callback, ( void * ) NULL, 1200U ); + #else + uint32_t ulIPAddress = FreeRTOS_gethostbyname( pcServerName ); + + if( ulIPAddress != 0U ) + { + vDNS_callback( pcServerName, NULL, ulIPAddress ); + } + #endif + #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ + } + else + { + xStatus = EStatusAsking; + } + + break; + + case EStatusAsking: + prvNTPPacketInit(); + uxSendTime = xTaskGetTickCount(); + #if ( ipconfigUSE_IPv6 != 0 ) + if( memcmp( xIPAddressFound.sin_addr6.ucBytes, in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) + { + FreeRTOS_printf( ( "Sending UDP message to %pip:%u\n", + xIPAddressFound.sin_addr6.ucBytes, + FreeRTOS_ntohs( xIPAddressFound.sin_port ) ) ); + + FreeRTOS_sendto( xNTP_UDPSocket, + ( void * ) &xNTPPacket, sizeof( xNTPPacket ), + 0, + ( const struct freertos_sockaddr * ) &( xIPAddressFound ), + sizeof( xIPAddressFound ) ); + } + else + #endif /* ( ipconfigUSE_IPv6 != 0 ) */ + { + xAddress.sin_addr = ulIPAddressFound; + xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); + + FreeRTOS_printf( ( "Sending UDP message to %xip:%u\n", + ( unsigned ) FreeRTOS_ntohl( xAddress.sin_addr ), + ( unsigned ) FreeRTOS_ntohs( xAddress.sin_port ) ) ); + + FreeRTOS_sendto( xNTP_UDPSocket, + ( void * ) &xNTPPacket, + sizeof( xNTPPacket ), + 0, &( xAddress ), + sizeof( xAddress ) ); + } + + break; + + case EStatusPause: + break; + + case EStatusFailed: + break; + } + + #if ( ipconfigUSE_CALLBACKS != 0 ) + { + xSemaphoreTake( xNTPWakeupSem, 5000 ); + } + #else + { + uint32_t xAddressSize; + BaseType_t xReturned; + + xAddressSize = sizeof( xAddress ); + xReturned = FreeRTOS_recvfrom( xNTP_UDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize ); + + switch( xReturned ) + { + case 0: + case -pdFREERTOS_ERRNO_EAGAIN: + case -pdFREERTOS_ERRNO_EINTR: + break; + + default: + + if( xReturned < sizeof( xNTPPacket ) ) + { + FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) ); + } + else + { + prvReadTime( ( struct SNtpPacket * ) cRecvBuffer ); + + if( xStatus != EStatusPause ) + { + xStatus = EStatusPause; + } + } + + break; + } + } + #endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */ + } +} +/*-----------------------------------------------------------*/ diff --git a/tools/tcp_utilities/include/NTPDemo.h b/tools/tcp_utilities/include/NTPDemo.h new file mode 100644 index 0000000000..f77a0aff52 --- /dev/null +++ b/tools/tcp_utilities/include/NTPDemo.h @@ -0,0 +1,55 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + */ + +/* + * A simple demo for NTP using FreeRTOS+TCP + */ + +#ifndef NTPDEMO_H + +#define NTPDEMO_H + +void vStartNTPTask( uint16_t usTaskStackSize, + UBaseType_t uxTaskPriority ); + +/* + * xIPVersion = 4 or 6. + * xAsynchronous = true for asynchronous DNS lookups. + * xLogging = true to get more logging. + */ +void vNTPSetNTPType( BaseType_t aIPType, + BaseType_t xAsynchronous, + BaseType_t xLogging ); + +/* Delete the IP-addresses of the NTP server to force a DNS lookup. */ +void vNTPClearCache( void ); + +/* Check if the NTP task is running. */ +BaseType_t xNTPTaskIsRunning( void ); + +extern BaseType_t xNTPHasTime; +extern uint32_t ulNTPTime; + +#endif /* ifndef NTPDEMO_H */ diff --git a/tools/tcp_utilities/include/date_and_time.h b/tools/tcp_utilities/include/date_and_time.h new file mode 100644 index 0000000000..2bf2bbba76 --- /dev/null +++ b/tools/tcp_utilities/include/date_and_time.h @@ -0,0 +1,94 @@ +/* + * FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd. + * All rights reserved + * + * VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + * + * This file is part of the FreeRTOS distribution. + * + * FreeRTOS is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License (version 2) as published by the + * Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + * + *************************************************************************** + * >>! NOTE: The modification to the GPL is included to allow you to !<< + * >>! distribute a combined work that includes FreeRTOS without being !<< + * >>! obliged to provide the source code for proprietary components !<< + * >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + * + * FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. Full license text is available on the following + * link: http://www.freertos.org/a00114.html + * + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + * + * http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + * the FAQ page "My application does not run, what could be wrong?". Have you + * defined configASSERT()? + * + * http://www.FreeRTOS.org/support - In return for receiving this top quality + * embedded software for free we request you assist our global community by + * participating in the support forum. + * + * http://www.FreeRTOS.org/training - Investing in training allows your team to + * be as productive as possible as early as possible. Now you can receive + * FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + * Ltd, and the world's leading authority on the world's leading RTOS. + * + * http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + * including FreeRTOS+Trace - an indispensable productivity tool, a DOS + * compatible FAT file system, and our tiny thread aware UDP/IP stack. + * + * http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + * Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + * + * http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + * Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + * licenses offer ticketed support, indemnification and commercial middleware. + * + * http://www.SafeRTOS.com - High Integrity Systems also provide a safety + * engineered and independently SIL3 certified version for use in safety and + * mission critical applications that require provable dependability. + * + * 1 tab == 4 spaces! + */ + +#ifndef DATE_AND_TIME_H + #define DATE_AND_TIME_H + + #ifdef __cplusplus + extern "C" { + #endif + + #include + + extern uint32_t ulSeconds, ulMsec; + extern int iTimeZone; + + extern time_t FreeRTOS_get_secs_msec( time_t * pulMsec ); + extern void FreeRTOS_set_secs_msec( time_t * pulSeconds, + time_t * pulMsec ); + + extern time_t FreeRTOS_time( time_t * pxTime ); + extern void FreeRTOS_settime( time_t * pxTime ); + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + +#endif /* DATE_AND_TIME_H */ diff --git a/tools/tcp_utilities/include/http_client_test.h b/tools/tcp_utilities/include/http_client_test.h new file mode 100644 index 0000000000..20bf572f76 --- /dev/null +++ b/tools/tcp_utilities/include/http_client_test.h @@ -0,0 +1,23 @@ +/* + * FreeRTOS V8.2.2 - Copyright (C) 2015 Real Time Engineers Ltd. + * All rights reserved + */ + +#ifndef HTTP_CLIENT_TEST_H +#define HTTP_CLIENT_TEST_H + +/* Wake-up a HTTP client task. aIndex */ +void wakeupHTTPClient( size_t uxIndex, + const char * pcHost, + const char * pcFileName, + uint16_t usPortNumber, + BaseType_t xIPType ); + +/* + * Create the TCP (HTTP) echo client tasks. + */ +void vStartHTTPClientTest( uint16_t usTaskStackSize, + UBaseType_t uxTaskPriority ); +BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void ); + +#endif /* HTTP_CLIENT_TEST_H */ diff --git a/tools/tcp_utilities/include/ntpClient.h b/tools/tcp_utilities/include/ntpClient.h new file mode 100644 index 0000000000..ff4434cb92 --- /dev/null +++ b/tools/tcp_utilities/include/ntpClient.h @@ -0,0 +1,103 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + */ + +/* */ +/* ntpClient.h */ +/* */ + +#ifndef __NTPCLIENT_H__ + +#define __NTPCLIENT_H__ + +#define NTP_PORT 123 + +typedef uint32_t quint32; +typedef int32_t qint32; +typedef uint8_t quint8; +typedef int8_t qint8; + +typedef union _SNtpFlags SNtpFlags; + +#ifdef _MSC_VER + #define __attribute__( x ) +#endif + +/** + * 64-bit NTP timestamp. + */ +struct __attribute__( ( __packed__ ) ) _SNtpTimestamp +{ + /** Number of seconds passed since Jan 1 1900, in big-endian format. */ + quint32 seconds; + + /** Fractional time part, in 1/0xFFFFFFFFs of a second. */ + quint32 fraction; +}; + +typedef struct _SNtpTimestamp SNtpTimestamp; + +/** + * Mandatory part of an NTP packet + */ +struct SNtpPacket +{ + /** Flags. */ + unsigned char flags; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */ + + /** Stratum of the clock. */ + quint8 stratum; /* value 0 : unspecified */ + + /** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */ + qint8 poll; /* 10 means 1 << 10 = 1024 seconds */ + + /** Precision of the clock, in log2 seconds. Note that the value is signed. */ + qint8 precision; /* 0xFA = 250 = 0.015625 seconds */ + + /** Round trip time to the primary reference source, in NTP short format. */ + qint32 rootDelay; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */ + + /** Nominal error relative to the primary reference source. */ + qint32 rootDispersion; /* 0x0008 CAC8 = 8.7912 seconds */ + + /** Reference identifier (either a 4 character string or an IP address). */ + qint8 referenceID[ 4 ]; /* or just 0000 */ + + /** The time at which the clock was last set or corrected. */ + SNtpTimestamp referenceTimestamp; /* Current time */ + + /** The time at which the request departed the client for the server. */ + SNtpTimestamp originateTimestamp; /* Keep 0 */ + + /** The time at which the request arrived at the server. */ + SNtpTimestamp receiveTimestamp; /* Keep 0 */ + + /** The time at which the reply departed the server for client. */ + SNtpTimestamp transmitTimestamp; +}; + +/* Add this number to get secs since 1-1-1900 */ +#define TIME1970 2208988800UL + +#endif /* __NTPCLIENT_H__ */ diff --git a/tools/tcp_utilities/include/plus_tcp_demo_cli.h b/tools/tcp_utilities/include/plus_tcp_demo_cli.h new file mode 100644 index 0000000000..0399cb55fa --- /dev/null +++ b/tools/tcp_utilities/include/plus_tcp_demo_cli.h @@ -0,0 +1,42 @@ +/* + * plus_tcp_demo_cli.h + * + * This module will handle a set of commands that help with integration testing. + */ + +#ifndef PLUS_TCP_DEMO_CLI_H + + #if __cplusplus + extern "C" { + #endif + +/* + * Handle a CLI command. + * Returns zero when the command was recognised and handled. + */ + BaseType_t xHandleTestingCommand( char * pcBuffer, + size_t uxBufferSize ); + +/* + * Do the regular checks. + */ + void xHandleTesting( void ); + + #if ( ipconfigMULTI_INTERFACE != 0 ) + +/* + * Show all properties of an end-point. + */ + void showEndPoint( NetworkEndPoint_t * pxEndPoint ); + #endif + +/*/ * 'xServerSemaphore' should be declared in main.c * / */ +/*extern SemaphoreHandle_t xServerSemaphore; */ + + #if __cplusplus + } /* extern "C" */ + #endif + + extern int verboseLevel; + +#endif /* PLUS_TCP_DEMO_CLI_H */ diff --git a/tools/tcp_utilities/include/tcp_dump_packets.h b/tools/tcp_utilities/include/tcp_dump_packets.h index d68741507e..6edb1cd34f 100644 --- a/tools/tcp_utilities/include/tcp_dump_packets.h +++ b/tools/tcp_utilities/include/tcp_dump_packets.h @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -59,8 +57,7 @@ #define flag_FRAME_6 0x00020000UL #define flag_Unknown_FRAME 0x00040000UL -/** - * Structure to hold information about one dump entry. +/** @brief Structure to hold information about one dump entry. */ typedef struct xDumpEntry { @@ -69,19 +66,13 @@ typedef struct xDumpEntry size_t uxCount; /**< The count of the entry */ } DumpEntry_t; -/** - * Structure to hold information of all the entries in this data dump. - */ +/** @brief Structure to hold information of all the entries in this data dump. */ typedef struct xDumpEntries { size_t uxEntryCount; /**< The number of entries*/ DumpEntry_t xEntries[ dumpMAX_DUMP_ENTRIES ]; /**< Array of struct for all the entries */ } DumpEntries_t; -/* - * - */ - #if ( ipconfigUSE_DUMP_PACKETS != 0 ) extern void dump_packet_init( const char * pcFileName, diff --git a/tools/tcp_utilities/include/tcp_mem_stats.h b/tools/tcp_utilities/include/tcp_mem_stats.h index a84d64cc38..b077df8ae1 100644 --- a/tools/tcp_utilities/include/tcp_mem_stats.h +++ b/tools/tcp_utilities/include/tcp_mem_stats.h @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 diff --git a/tools/tcp_utilities/include/tcp_netstat.h b/tools/tcp_utilities/include/tcp_netstat.h index 8797946461..908e74ff67 100644 --- a/tools/tcp_utilities/include/tcp_netstat.h +++ b/tools/tcp_utilities/include/tcp_netstat.h @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -101,7 +99,7 @@ typedef struct TCPSocketList_t xTCPSocketList; UDPSocketList_t xUDPSocketList; IOCounters_t xInput; - IOCounters_t xOutput; + IOCounters_t XOutput; } MetricsType_t; extern BaseType_t vGetMetrics( MetricsType_t * pxMetrics ); diff --git a/tools/tcp_utilities/plus_tcp_demo_cli.c b/tools/tcp_utilities/plus_tcp_demo_cli.c new file mode 100644 index 0000000000..d116a95003 --- /dev/null +++ b/tools/tcp_utilities/plus_tcp_demo_cli.c @@ -0,0 +1,1614 @@ +/* + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 +#include +#include + +/* FreeRTOS includes. */ +#include +#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 ); + +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 ); + +#if ( ipconfigUSE_IPv6 == 0 ) + /* In the old days, an IP-address was just a number. */ + static void vDNSEvent( const char * pcName, + void * pvSearchID, + uint32_t ulIPAddress ); +#else + /* freertos_addrinfo can contain either an IPv4 or an IPv6 address. */ + static void vDNSEvent( const char * pcName, + void * pvSearchID, + struct freertos_addrinfo * pxAddrInfo ); +#endif + +#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; +} +/*-----------------------------------------------------------*/ + +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; +} +/*-----------------------------------------------------------*/ + +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; + + if( xIPType == 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" ) ); + } + else + { + 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" ) ); + } + + 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; + + if( xIPType == 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" ) ); + } + } + else + { + FreeRTOS_printf( ( "handle_arpq: Looking up %xip\n", + ( unsigned ) FreeRTOS_ntohl( ulLookUpIP ) ) ); + + xARPWaitResolution( ulLookUpIP, 1000U ); + } + + /* Let the IP-task do its work, and wait 500 ms. */ + FreeRTOS_printf( ( "... Pause ...\n" ) ); + vTaskDelay( pdMS_TO_TICKS( 500U ) ); + + if( xIPType == ipTYPE_IPv6 ) + { + eResult = eNDGetCacheEntry( &( xLookupAddress.xIP_IPv6 ), &xMACAddress, &pxEndPoint ); + } + else + { + eResult = eARPGetCacheEntry( &ulLookUpIP, &xMACAddress, &pxEndPoint ); + } + + 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 \n" ) ); + } + } +/*-----------------------------------------------------------*/ + +#else /* if ( ipconfigMULTI_INTERFACE != 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 \n" ) ); + } + } +#endif /* ( ipconfigMULTI_INTERFACE != 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, 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 ) + { + #if ( ipconfigUSE_IPv6 != 0 ) + if( xOptions.xIPVersion == 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(); + } + else + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + { + FreeRTOS_printf( ( "ping4 to '%s' (%xip)\n", pcHostname, ( unsigned ) FreeRTOS_ntohl( pxDNSResult->ai_addr->sin_addr ) ) ); + xPing4Count = 0; + #if ( ipconfigUSE_IPv6 != 0 ) + xPing6Count = -1; + #endif + ulPingIPAddress = pxDNSResult->ai_addr->sin_addr; + xARPWaitResolution( ulPingIPAddress, pdMS_TO_TICKS( 5000U ) ); + FreeRTOS_SendPingRequest( ulPingIPAddress, uxPingSize, PING_TIMEOUT ); + uxPingTimes[ 0 ] = ( TickType_t ) ullGetHighResolutionTime(); + } + } + 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 \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_addr6.ucBytes, ( int ) rc ) ); + } + else + #endif /* ipconfigUSE_IPv6 */ + { + uint32_t luIPAddress = pxResult->ai_addr->sin_addr; + 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 ) ); + + #if ( ipconfigUSE_IPv6 != 0 ) + { + pxResult->ai_addr = ( struct freertos_sockaddr * ) &( pxResult->xPrivateStorage.sockaddr ); + } + #else + { + pxResult->ai_addr = &( pxResult->xPrivateStorage.sockaddr4 ); + } + #endif + + #if ( ipconfigUSE_IPv6 != 0 ) + 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 ); + } + else + #endif /* ( ipconfigUSE_IPv6 != 0 ) */ + { + #if ( ipconfigUSE_DNS_CACHE != 0 ) + ulIpAddress = FreeRTOS_dnslookup( pcHost ); + FreeRTOS_printf( ( "Lookup4 '%s' = %lxip\n", pcHost, FreeRTOS_ntohl( ulIpAddress ) ) ); + pxResult->ai_addr->sin_addr = ulIpAddress; + pxResult->ai_family = FREERTOS_AF_INET4; + pxResult->ai_addrlen = ipSIZE_OF_IPv4_ADDRESS; + #endif + } + } + } + #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 ) */ +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_IPv6 != 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 ) ); + + if( pxAddrInfo->ai_family == 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 ) ); + } + } + else + { + 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 ) ) ); + } + } + } + + if( xServerWorkTaskHandle != NULL ) + { + xDNSCount++; + xTaskNotifyGive( xServerWorkTaskHandle ); + } + } +#else /* if ( ipconfigUSE_IPv6 != 0 ) */ + static void vDNSEvent( const char * pcName, + void * pvSearchID, + uint32_t ulIPAddress ) + { + ( void ) pvSearchID; + + FreeRTOS_printf( ( "vDNSEvent: found '%s' on %lxip\n", pcName, FreeRTOS_ntohl( ulIPAddress ) ) ); + + if( xServerWorkTaskHandle != NULL ) + { + xDNSCount++; + xTaskNotifyGive( xServerWorkTaskHandle ); + } + } +#endif /* if ( ipconfigUSE_IPv6 != 0 ) */ +/*-----------------------------------------------------------*/ + +#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(); + FreeRTOS_ClearND(); + } + #endif /* ipconfigUSE_DNS_CACHE */ + #if ( ipconfigMULTI_INTERFACE != 0 ) + FreeRTOS_ClearARP( NULL ); + #else + FreeRTOS_ClearARP(); + #endif + FreeRTOS_printf( ( "Cleared caches.\n" ) ); +} +/*-----------------------------------------------------------*/ diff --git a/tools/tcp_utilities/tcp_dump_packets.c b/tools/tcp_utilities/tcp_dump_packets.c index cf4b014789..341da72cea 100644 --- a/tools/tcp_utilities/tcp_dump_packets.c +++ b/tools/tcp_utilities/tcp_dump_packets.c @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 diff --git a/tools/tcp_utilities/tcp_mem_stats.c b/tools/tcp_utilities/tcp_mem_stats.c index 7e1870f7fb..b3a45be7fe 100644 --- a/tools/tcp_utilities/tcp_mem_stats.c +++ b/tools/tcp_utilities/tcp_mem_stats.c @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -49,19 +47,12 @@ #include "tcp_mem_stats.h" -#if ( ipconfigUSE_TCP_MEM_STATS != 0 ) - - #ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION +#ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION + #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u + #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" +#endif -/* Define the maximum number of objects ( memory allocations by - * the IP-stack ) that will be recorded. */ - #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u - -/* If you don't want to see this pragma message, you can either - * remove it or define 'ipconfigTCP_MEM_STATS_MAX_ALLOCATION' in - * your freeRTOSIPConfig.h. */ - #pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?") - #endif +#if ( ipconfigUSE_TCP_MEM_STATS != 0 ) /* When a streambuffer is allocated, 4 extra bytes will be reserved. */ @@ -113,21 +104,21 @@ { /* Already added, strange. */ FreeRTOS_printf( ( "vAddAllocation: Pointer %p already added\n", pxObject ) ); - break; + return; } } - /* If the object has not been found, - * and if there is still space, add the object. */ - if( ( uxIndex == uxAllocationCount ) && - ( uxAllocationCount < ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) ) + if( uxAllocationCount >= ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) { - xAllocations[ uxIndex ].pxObject = pxObject; - xAllocations[ uxIndex ].xMemType = xMemType; - xAllocations[ uxIndex ].uxSize = uxSize; - xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++; - uxAllocationCount++; + /* The table is full. */ + return; } + + xAllocations[ uxIndex ].pxObject = pxObject; + xAllocations[ uxIndex ].xMemType = xMemType; + xAllocations[ uxIndex ].uxSize = uxSize; + xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++; + uxAllocationCount++; } xTaskResumeAll(); } diff --git a/tools/tcp_utilities/tcp_netstat.c b/tools/tcp_utilities/tcp_netstat.c index f516fe7d5a..284f934cc0 100644 --- a/tools/tcp_utilities/tcp_netstat.c +++ b/tools/tcp_utilities/tcp_netstat.c @@ -1,8 +1,6 @@ /* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT + * FreeRTOS+TCP V2.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -48,8 +46,7 @@ extern List_t xBoundUDPSocketsList; extern List_t xBoundTCPSocketsList; #endif /* ipconfigUSE_TCP == 1 */ -IOCounters_t xInputCounters = { 0U }; -IOCounters_t xOutputCounters = { 0U }; +IOCounters_t xInputCounters, xOutputCounters; BaseType_t vGetMetrics( MetricsType_t * pxMetrics ) { @@ -62,7 +59,7 @@ BaseType_t vGetMetrics( MetricsType_t * pxMetrics ) memset( pxMetrics, 0, sizeof *pxMetrics ); pxMetrics->xInput = xInputCounters; - pxMetrics->xOutput = xOutputCounters; + pxMetrics->XOutput = xOutputCounters; if( !listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) ) { @@ -103,7 +100,7 @@ BaseType_t vGetMetrics( MetricsType_t * pxMetrics ) size_t uxCount = pxMetrics->xTCPSocketList.uxCount; pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usLocalPort = pxSocket->usLocalPort; - pxMetrics->xTCPSocketList.xTCPList[ uxCount ].ulRemoteIP = pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4; + pxMetrics->xTCPSocketList.xTCPList[ uxCount ].ulRemoteIP = pxSocket->u.xTCP.ulRemoteIP; pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usRemotePort = pxSocket->u.xTCP.usRemotePort; pxMetrics->xTCPSocketList.uxCount++; } @@ -154,8 +151,8 @@ void vShowMetrics( const MetricsType_t * pxMetrics ) pxMetrics->xInput.uxPacketCount, pxMetrics->xInput.uxByteCount ) ); FreeRTOS_printf( ( " Output : %5lu packets, %5lu bytes\n", - pxMetrics->xOutput.uxPacketCount, - pxMetrics->xOutput.uxByteCount ) ); + pxMetrics->XOutput.uxPacketCount, + pxMetrics->XOutput.uxByteCount ) ); #if ( ipconfigUSE_TCP == 1 ) { From 0a06449594bfadd8022c478453f338363049d82a Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Tue, 21 Feb 2023 17:04:38 +0800 Subject: [PATCH 2/8] Some more change in dev_integration_hein.v8 --- source/FreeRTOS_ARP.c | 83 ++++++++++---- source/FreeRTOS_DNS_Parser.c | 21 ++-- source/FreeRTOS_IP.c | 39 ++++--- source/FreeRTOS_ND.c | 144 +++++++++++++++++------- source/FreeRTOS_Routing.c | 27 ++--- source/FreeRTOS_Sockets.c | 2 +- source/FreeRTOS_TCP_IP.c | 22 +++- source/FreeRTOS_TCP_Transmission_IPV4.c | 13 ++- source/FreeRTOS_TCP_Transmission_IPV6.c | 20 +++- source/FreeRTOS_UDP_IPv6.c | 26 ++--- 10 files changed, 274 insertions(+), 123 deletions(-) diff --git a/source/FreeRTOS_ARP.c b/source/FreeRTOS_ARP.c index 2cc268e69d..d47a33f93d 100644 --- a/source/FreeRTOS_ARP.c +++ b/source/FreeRTOS_ARP.c @@ -151,10 +151,6 @@ eFrameProcessingResult_t eARPProcessPacket( const NetworkBufferDescriptor_t * px void * pvCopyDest; NetworkEndPoint_t * pxTargetEndPoint = pxNetworkBuffer->pxEndPoint; - #if ( ipconfigARP_USE_CLASH_DETECTION != 0 ) - NetworkEndPoint_t * pxSourceEndPoint; - #endif - /* Next defensive request must not be sent for arpIP_CLASH_RESET_TIMEOUT_MS * period. */ static TickType_t uxARPClashTimeoutPeriod = pdMS_TO_TICKS( arpIP_CLASH_RESET_TIMEOUT_MS ); @@ -241,6 +237,8 @@ eFrameProcessingResult_t eARPProcessPacket( const NetworkBufferDescriptor_t * px /* Process received ARP frame to see if there is a clash. */ #if ( ipconfigARP_USE_CLASH_DETECTION != 0 ) { + NetworkEndPoint_t * pxSourceEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulSenderProtocolAddress, 2 ); + if( ( pxSourceEndPoint != NULL ) && ( pxSourceEndPoint->ipv4_settings.ulIPAddress == ulSenderProtocolAddress ) ) { xARPHadIPClash = pdTRUE; @@ -417,7 +415,8 @@ static void vARPProcessPacketReply( const ARPPacket_t * pxARPFrame, vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress, pxTargetEndPoint ); } - if( pxARPWaitingNetworkBuffer != NULL ) + if( ( pxARPWaitingNetworkBuffer != NULL ) && + ( uxIPHeaderSizePacket( pxARPWaitingNetworkBuffer ) == ipSIZE_OF_IPv4_HEADER ) ) { /* MISRA Ref 11.3.1 [Misaligned access] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ @@ -497,24 +496,70 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw { BaseType_t xNeedsARPResolution = pdFALSE; - /* MISRA Ref 11.3.1 [Misaligned access] */ -/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ - /* coverity[misra_c_2012_rule_11_3_violation] */ - const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); - const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader ); - IPV4Parameters_t * pxIPv4Settings = &( pxNetworkBuffer->pxEndPoint->ipv4_settings ); + if( uxIPHeaderSizePacket( pxNetworkBuffer ) == ipSIZE_OF_IPv6_HEADER ) + { + const IPPacket_IPv6_t * pxIPPacket = ( ( IPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); + const IPHeader_IPv6_t * pxIPHeader = &( pxIPPacket->xIPHeader ); + IPv6_Address_t * pxIPAddress = &( pxIPHeader->xSourceAddress ); + uint8_t ucNextHeader = pxIPHeader->ucNextHeader; + + if( ( ucNextHeader == ipPROTOCOL_TCP ) || + ( ucNextHeader == ipPROTOCOL_UDP ) ) + { + IPv6_Type_t eType = xIPv6_GetIPType( pxIPAddress ); + FreeRTOS_printf( ( "xCheckRequiresARPResolution: %pip type %s\n", pxIPAddress->ucBytes, ( eType == eIPv6_Global ) ? "Global" : ( eType == eIPv6_LinkLocal ) ? "LinkLocal" : "other" ) ); + + if( eType == eIPv6_LinkLocal ) + { + MACAddress_t xMACAddress; + NetworkEndPoint_t * pxEndPoint; + eARPLookupResult_t eResult; + char pcName[ 80 ]; + + eResult = eNDGetCacheEntry( pxIPAddress, &xMACAddress, &pxEndPoint ); + FreeRTOS_printf( ( "xCheckRequiresARPResolution: eResult %s with EP %s\n", ( eResult == eARPCacheMiss ) ? "Miss" : ( eResult == eARPCacheHit ) ? "Hit" : "Error", pcEndpointName( pxEndPoint, pcName, sizeof pcName ) ) ); + + if( eResult == eARPCacheMiss ) + { + NetworkBufferDescriptor_t * pxTempBuffer; + size_t uxNeededSize; + + uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPRouterSolicitation_IPv6_t ); + pxTempBuffer = pxGetNetworkBufferWithDescriptor( BUFFER_FROM_WHERE_CALL( 199 ) uxNeededSize, 0U ); - if( ( pxIPHeader->ulSourceIPAddress & pxIPv4Settings->ulNetMask ) == ( pxIPv4Settings->ulIPAddress & pxIPv4Settings->ulNetMask ) ) + if( pxTempBuffer != NULL ) + { + pxTempBuffer->pxEndPoint = pxNetworkBuffer->pxEndPoint; + pxTempBuffer->pxInterface = pxNetworkBuffer->pxInterface; + vNDSendNeighbourSolicitation( pxNetworkBuffer, pxIPAddress ); + } + + xNeedsARPResolution = pdTRUE; + } + } + } + } + else { - /* If the IP is on the same subnet and we do not have an ARP entry already, - * then we should send out ARP for finding the MAC address. */ - if( xIsIPInARPCache( pxIPHeader->ulSourceIPAddress ) == pdFALSE ) + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); + const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader ); + IPV4Parameters_t * pxIPv4Settings = &( pxNetworkBuffer->pxEndPoint->ipv4_settings ); + + if( ( pxIPHeader->ulSourceIPAddress & pxIPv4Settings->ulNetMask ) == ( pxIPv4Settings->ulIPAddress & pxIPv4Settings->ulNetMask ) ) { - FreeRTOS_OutputARPRequest( pxIPHeader->ulSourceIPAddress ); + /* If the IP is on the same subnet and we do not have an ARP entry already, + * then we should send out ARP for finding the MAC address. */ + if( xIsIPInARPCache( pxIPHeader->ulSourceIPAddress ) == pdFALSE ) + { + FreeRTOS_OutputARPRequest( pxIPHeader->ulSourceIPAddress ); - /* This packet needs resolution since this is on the same subnet - * but not in the ARP cache. */ - xNeedsARPResolution = pdTRUE; + /* This packet needs resolution since this is on the same subnet + * but not in the ARP cache. */ + xNeedsARPResolution = pdTRUE; + } } } diff --git a/source/FreeRTOS_DNS_Parser.c b/source/FreeRTOS_DNS_Parser.c index 5c322eef74..b868785eda 100644 --- a/source/FreeRTOS_DNS_Parser.c +++ b/source/FreeRTOS_DNS_Parser.c @@ -438,6 +438,7 @@ { NetworkBufferDescriptor_t * pxNetworkBuffer; NetworkEndPoint_t * pxEndPoint, xEndPoint; + size_t uxUDPOffset; pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer ); @@ -450,6 +451,9 @@ break; } + uxUDPOffset = ( size_t ) ( pucUDPPayloadBuffer - pxNetworkBuffer->pucEthernetBuffer ); + configASSERT( ( uxUDPOffset == ipIP_PAYLOAD_OFFSET ) || ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv6 ) ); + if( pxNetworkBuffer->pxEndPoint == NULL ) { /* NetworkInterface is obliged to set 'pxEndPoint' in every received packet, @@ -480,8 +484,8 @@ } #endif /* ( ipconfigUSE_IPv6 != 0 ) */ - /* If this is not a reply to our DNS request, it might an LLMNR - * request. */ + /* If this is not a reply to our DNS request, it might be an mDNS or an LLMNR + * request. Ask the application if it uses the name. */ if( xApplicationDNSQueryHook( &xEndPoint, xSet.pcName ) ) { int16_t usLength; @@ -524,7 +528,7 @@ xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) xSet.pcRequestedName ) - pucUDPPayloadBuffer ); pxNetworkBuffer = pxNewBuffer; - pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ); + pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] ); xSet.pucByte = &( pucNewBuffer[ xOffset1 ] ); xSet.pcRequestedName = ( char * ) &( pucNewBuffer[ xOffset2 ] ); @@ -538,7 +542,7 @@ } else { - pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ); + pucNewBuffer = &( pxNetworkBuffer->pucEthernetBuffer[ uxUDPOffset ] ); } } @@ -575,11 +579,11 @@ } else { - /*logging*/ - FreeRTOS_printf( ( "LLMNR return IPv4 %lxip\n", FreeRTOS_ntohl( xEndPoint.ipv4_settings.ulIPAddress ) ) ); + size_t uxDistance; vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, ( uint16_t ) sizeof( pxAnswer->ulIPAddress ) ); vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( xEndPoint.ipv4_settings.ulIPAddress ) ); - usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( xSet.pucByte - pucNewBuffer ) ); + uxDistance = ( size_t ) ( xSet.pucByte - pucNewBuffer ); + usLength = ( int16_t ) ( sizeof( *pxAnswer ) + uxDistance ); } prepareReplyDNSMessage( pxNetworkBuffer, usLength ); @@ -956,14 +960,15 @@ if( pxIPHeader->ulDestinationIPAddress == ipMDNS_IP_ADDRESS ) { pxIPHeader->ulDestinationIPAddress = ipMDNS_IP_ADDRESS; + pxIPHeader->ucTimeToLive = ipMDNS_TIME_TO_LIVE; } else { pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress; + pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE; } pxIPHeader->ulSourceIPAddress = ( pxEndPoint != NULL ) ? pxEndPoint->ipv4_settings.ulIPAddress : 0U; - pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE; pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier ); /* The stack doesn't support fragments, so the fragment offset field must always be zero. diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index 0666d50e85..0c2d7e6e02 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -1772,31 +1772,32 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke * entry. */ if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP ) { - /* Refresh the ARP cache with the IP/MAC-address of the received - * packet. For UDP packets, this will be done later in - * xProcessReceivedUDPPacket(), as soon as it's know that the message - * will be handled. This will prevent the ARP cache getting - * overwritten with the IP address of useless broadcast packets. */ - if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) - { - vNDRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), &( pxIPHeader_IPv6->xSourceAddress ), pxNetworkBuffer->pxEndPoint ); - } - else - if( xCheckRequiresARPResolution( pxNetworkBuffer ) == pdTRUE ) { eReturn = eWaitingARPResolution; } else { - /* IP address is not on the same subnet, ARP table can be updated. - * Refresh the ARP cache with the IP/MAC-address of the received - * packet. For UDP packets, this will be done later in + /* Refresh the ARP cache with the IP/MAC-address of the received + * packet. For UDP packets, this will be done later in * xProcessReceivedUDPPacket(), as soon as it's know that the message * will be handled. This will prevent the ARP cache getting - * overwritten with the IP address of useless broadcast packets. - */ - vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress, pxNetworkBuffer->pxEndPoint ); + * overwritten with the IP address of useless broadcast packets. */ + if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) + { + vNDRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), &( pxIPHeader_IPv6->xSourceAddress ), pxNetworkBuffer->pxEndPoint ); + } + else + { + /* IP address is not on the same subnet, ARP table can be updated. + * Refresh the ARP cache with the IP/MAC-address of the received + * packet. For UDP packets, this will be done later in + * xProcessReceivedUDPPacket(), as soon as it's know that the message + * will be handled. This will prevent the ARP cache getting + * overwritten with the IP address of useless broadcast packets. + */ + vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress, pxNetworkBuffer->pxEndPoint ); + } } } @@ -1812,7 +1813,9 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke * went wrong because it will not be able to validate what it * receives. */ #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) - eReturn = ProcessICMPPacket( pxNetworkBuffer ); + { + eReturn = ProcessICMPPacket( pxNetworkBuffer ); + } #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */ break; diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index 2e656803bc..ab5a020520 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -45,6 +45,8 @@ #include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_Routing.h" #include "FreeRTOS_ND.h" +#include "FreeRTOS_IP_Timers.h" + #if ( ipconfigUSE_LLMNR == 1 ) #include "FreeRTOS_DNS.h" #endif /* ipconfigUSE_LLMNR */ @@ -204,7 +206,11 @@ if( pxEndPoint != NULL ) { - *( ppxEndPoint ) = pxEndPoint; + if( ppxEndPoint != NULL ) + { + *( ppxEndPoint ) = pxEndPoint; + } + FreeRTOS_printf( ( "eNDGetCacheEntry: FindEndPointOnIP failed for %pip (endpoint %pip)\n", pxIPAddress->ucBytes, pxEndPoint->ipv6_settings.xIPAddress.ucBytes ) ); @@ -338,46 +344,48 @@ * When the age reaches zero it is no longer considered valid. */ ( xNDCache[ x ].ucAge )--; - /* If the entry is not yet valid, then it is waiting an ND - * advertisement, and the ND solicitation should be retransmitted. */ - if( xNDCache[ x ].ucValid == ( uint8_t ) pdFALSE ) - { - xDoSolicitate = pdTRUE; - } - else if( xNDCache[ x ].ucAge <= ( uint8_t ) ndMAX_CACHE_AGE_BEFORE_NEW_ND_SOLICITATION ) + if( xNDCache[ x ].ucAge == 0U ) { - /* This entry will get removed soon. See if the MAC address is - * still valid to prevent this happening. */ - iptraceND_TABLE_ENTRY_WILL_EXPIRE( xNDCache[ x ].xIPAddress ); - xDoSolicitate = pdTRUE; + /* The entry is no longer valid. Wipe it out. */ + iptraceND_TABLE_ENTRY_EXPIRED( xNDCache[ x ].xIPAddress ); + ( void ) memset( &( xNDCache[ x ] ), 0, sizeof( xNDCache[ x ] ) ); } else { - /* The age has just ticked down, with nothing to do. */ - } + /* If the entry is not yet valid, then it is waiting an ND + * advertisement, and the ND solicitation should be retransmitted. */ + if( xNDCache[ x ].ucValid == ( uint8_t ) pdFALSE ) + { + xDoSolicitate = pdTRUE; + } + else if( xNDCache[ x ].ucAge <= ( uint8_t ) ndMAX_CACHE_AGE_BEFORE_NEW_ND_SOLICITATION ) + { + /* This entry will get removed soon. See if the MAC address is + * still valid to prevent this happening. */ + iptraceND_TABLE_ENTRY_WILL_EXPIRE( xNDCache[ x ].xIPAddress ); + xDoSolicitate = pdTRUE; + } + else + { + /* The age has just ticked down, with nothing to do. */ + } - if( xDoSolicitate != pdFALSE ) - { - size_t uxNeededSize; - NetworkBufferDescriptor_t * pxNetworkBuffer; + if( xDoSolicitate != pdFALSE ) + { + size_t uxNeededSize; + NetworkBufferDescriptor_t * pxNetworkBuffer; - uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPHeader_IPv6_t ); - pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxNeededSize, 0U ); + uxNeededSize = ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER + sizeof( ICMPHeader_IPv6_t ); + pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( uxNeededSize, 0U ); - if( pxNetworkBuffer != NULL ) - { - pxNetworkBuffer->pxEndPoint = xNDCache[ x ].pxEndPoint; - /* _HT_ From here I am suspecting a network buffer leak */ - vNDSendNeighbourSolicitation( pxNetworkBuffer, &( xNDCache[ x ].xIPAddress ) ); + if( pxNetworkBuffer != NULL ) + { + pxNetworkBuffer->pxEndPoint = xNDCache[ x ].pxEndPoint; + /* _HT_ From here I am suspecting a network buffer leak */ + vNDSendNeighbourSolicitation( pxNetworkBuffer, &( xNDCache[ x ].xIPAddress ) ); + } } } - - if( xNDCache[ x ].ucAge == 0U ) - { - /* The entry is no longer valid. Wipe it out. */ - iptraceND_TABLE_ENTRY_EXPIRED( xNDCache[ x ].xIPAddress ); - ( void ) memset( &( xNDCache[ x ] ), 0, sizeof( xNDCache[ x ] ) ); - } } } } @@ -419,7 +427,12 @@ { ( void ) memcpy( pxMACAddress->ucBytes, xNDCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ); eReturn = eARPCacheHit; - *ppxEndPoint = xNDCache[ x ].pxEndPoint; + + if( ppxEndPoint != NULL ) + { + *ppxEndPoint = xNDCache[ x ].pxEndPoint; + } + FreeRTOS_debug_printf( ( "prvCacheLookup6[ %d ] %pip with %02x:%02x:%02x:%02x:%02x:%02x\n", ( int ) x, pxAddressToLookup->ucBytes, @@ -440,7 +453,11 @@ if( eReturn == eARPCacheMiss ) { FreeRTOS_printf( ( "prvNDCacheLookup %pip Miss\n", pxAddressToLookup->ucBytes ) ); - *ppxEndPoint = NULL; + + if( ppxEndPoint != NULL ) + { + *ppxEndPoint = NULL; + } } return eReturn; @@ -462,8 +479,10 @@ if( xNDCache[ x ].ucValid != ( uint8_t ) 0U ) { /* See if the MAC-address also matches, and we're all happy */ - FreeRTOS_printf( ( "ND %2ld: age %3u - %pip MAC %02x-%02x-%02x-%02x-%02x-%02x\n", - x, + char pcBuffer[ 40 ]; + + FreeRTOS_printf( ( "ND %2d: age %3u - %pip MAC %02x-%02x-%02x-%02x-%02x-%02x endPoint %s\n", + ( int ) x, xNDCache[ x ].ucAge, xNDCache[ x ].xIPAddress.ucBytes, xNDCache[ x ].xMACAddress.ucBytes[ 0 ], @@ -471,7 +490,8 @@ xNDCache[ x ].xMACAddress.ucBytes[ 2 ], xNDCache[ x ].xMACAddress.ucBytes[ 3 ], xNDCache[ x ].xMACAddress.ucBytes[ 4 ], - xNDCache[ x ].xMACAddress.ucBytes[ 5 ] ) ); + xNDCache[ x ].xMACAddress.ucBytes[ 5 ], + pcEndpointName( xNDCache[ x ].pxEndPoint, pcBuffer, sizeof( pcBuffer ) ) ) ); xCount++; } } @@ -694,6 +714,7 @@ if( pxEndPoint == NULL ) { + /* No endpoint found for the target IP-address. */ FreeRTOS_printf( ( "SendPingRequestIPv6: no end-point found for %pip\n", pxIPAddress->ucBytes ) ); } @@ -777,7 +798,7 @@ } else { - /* There was not enough space to allocate a network buffer. */ + /* Either no proper end-pint found, or allocating the network buffer failed. */ } return xReturn; @@ -851,6 +872,42 @@ #endif /* ( ipconfigHAS_PRINTF == 1 ) */ /*-----------------------------------------------------------*/ +/** + * @brief When a neighbour advertisement has ben received, check if 'pxARPWaitingNetworkBuffer' + * was waiting for this new address look-up. If so, feed it to the IP-task as a new + * incoming packet. + */ + static void prvCheckWaitingBuffer( const IPv6_Address_t * pxIPv6Address ) + { + const IPPacket_IPv6_t * pxIPPacket = ( ( IPPacket_IPv6_t * ) pxARPWaitingNetworkBuffer->pucEthernetBuffer ); + const IPHeader_IPv6_t * pxIPHeader = &( pxIPPacket->xIPHeader ); + + if( memcmp( pxIPv6Address->ucBytes, pxIPHeader->xSourceAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) + { + FreeRTOS_printf( ( "Waiting done\n" ) ); + IPStackEvent_t xEventMessage; + const TickType_t xDontBlock = ( TickType_t ) 0; + + xEventMessage.eEventType = eNetworkRxEvent; + xEventMessage.pvData = ( void * ) pxARPWaitingNetworkBuffer; + + if( xSendEventStructToIPTask( &xEventMessage, xDontBlock ) != pdPASS ) + { + /* Failed to send the message, so release the network buffer. */ + vReleaseNetworkBufferAndDescriptor( BUFFER_FROM_WHERE_CALL( 140 ) pxARPWaitingNetworkBuffer ); + } + + /* Clear the buffer. */ + pxARPWaitingNetworkBuffer = NULL; + + /* Found an ARP resolution, disable ARP resolution timer. */ + vIPSetARPResolutionTimerEnableState( pdFALSE ); + + iptrace_DELAYED_ARP_REQUEST_REPLIED(); + } + } +/*-----------------------------------------------------------*/ + /** * @brief Process an ICMPv6 packet and send replies when applicable. * @@ -873,12 +930,13 @@ { if( pxICMPHeader_IPv6->ucTypeOfMessage != ipICMP_PING_REQUEST_IPv6 ) { - FreeRTOS_printf( ( "ICMPv6 %d (%s) from %pip to %pip end-point = %d\n", + char pcAddress[ 40 ]; + FreeRTOS_printf( ( "ICMPv6_recv %d (%s) from %pip to %pip end-point = %s\n", pxICMPHeader_IPv6->ucTypeOfMessage, pcMessageType( ( BaseType_t ) pxICMPHeader_IPv6->ucTypeOfMessage ), pxICMPPacket->xIPHeader.xSourceAddress.ucBytes, pxICMPPacket->xIPHeader.xDestinationAddress.ucBytes, - ( ( pxEndPoint != NULL ) && ( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) ) ? 1 : 0 ) ); + pcEndpointName( pxEndPoint, pcAddress, sizeof( pcAddress ) ) ) ); } } #endif /* ( ipconfigHAS_PRINTF == 1 ) */ @@ -1021,6 +1079,12 @@ vReceiveNA( pxNetworkBuffer ); #endif + if( ( pxARPWaitingNetworkBuffer != NULL ) && + ( uxIPHeaderSizePacket( pxARPWaitingNetworkBuffer ) == ipSIZE_OF_IPv6_HEADER ) ) + { + prvCheckWaitingBuffer( &( pxICMPHeader_IPv6->xIPv6Address ) ); + } + break; case ipICMP_ROUTER_SOLICITATION_IPv6: diff --git a/source/FreeRTOS_Routing.c b/source/FreeRTOS_Routing.c index 4863c7f07f..52b58874fe 100644 --- a/source/FreeRTOS_Routing.c +++ b/source/FreeRTOS_Routing.c @@ -698,10 +698,11 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, BaseType_t xIndex; BaseType_t xIsIPv6 = ( usFrameType == ipIPv6_FRAME_TYPE ) ? pdTRUE : pdFALSE; BaseType_t xGatewayTarget = pdFALSE; - IPv6_Type_t xTargetType = eIPv6_LinkLocal; + BaseType_t xTargetGlobal = pdFALSE; if( xIsIPv6 == pdTRUE ) { + /* Generic GW address fe80::1. */ static const uint8_t ucBytes[ 16 ] = { 0xfe, 0x80, 0x00, 0x00, @@ -718,7 +719,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, pxIPAddressTo->xIP_IPv6.ucBytes ) ); } - xTargetType = xIPv6_GetIPType( &( pxIPAddressTo->xIP_IPv6 ) ); + xTargetGlobal = ( xIPv6_GetIPType( &( pxIPAddressTo->xIP_IPv6 ) ) == eIPv6_Global ) ? pdTRUE : pdFALSE; } for( pxEndPoint = FreeRTOS_FirstEndPoint( pxNetworkInterface ); @@ -735,16 +736,14 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, if( xIsIPv6 != 0 ) { IPv6_Type_t xEndpointType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + BaseType_t xEndpointGlobal = ( xEndpointType == eIPv6_Global ) ? pdTRUE : pdFALSE; - if( ( memcmp( pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) || - ( ( xGatewayTarget == pdTRUE ) && ( xEndpointType == eIPv6_LinkLocal ) ) ) + if( ( memcmp( pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) ) { pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; xCount[ rMATCH_IP_ADDR ]++; } - - if( ( xTargetType == eIPv6_Multicast ) && - ( xEndpointType == eIPv6_LinkLocal ) ) + else if( xTargetGlobal == xEndpointGlobal ) { pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; xCount[ rMATCH_IP_ADDR ]++; @@ -761,11 +760,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, if( xSameMACAddress == pdTRUE ) { - if( ( pxFound[ rMATCH_MAC_ADDR ] == NULL ) || ( xIsIPv6 != ( uint32_t ) pxFound[ rMATCH_MAC_ADDR ]->bits.bIPv6 ) ) - { - xCount[ rMATCH_MAC_ADDR ]++; - } - + xCount[ rMATCH_MAC_ADDR ]++; pxFound[ rMATCH_MAC_ADDR ] = pxEndPoint; } } @@ -797,9 +792,9 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, FreeRTOS_printf( ( "EasyFit[%s]: %d %d %d ( %s ->%s ) %s\n", ( usFrameType == ipIPv6_FRAME_TYPE ) ? "IPv6" : ( usFrameType == ipIPv4_FRAME_TYPE ) ? "IPv4" : ( usFrameType == ipARP_FRAME_TYPE ) ? "ARP" : "UNK", - xCount[ 0 ], - xCount[ 1 ], - xCount[ 2 ], + ( unsigned ) xCount[ 0 ], + ( unsigned ) xCount[ 1 ], + ( unsigned ) xCount[ 2 ], pcBufferFrom, pcBufferTo, ( pxReturn == NULL ) ? "BAD" : "Good" ) ); @@ -888,7 +883,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, xIPAddressFrom.ulIP_IPv4 = pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress; } - FreeRTOS_printf( ( "pxEasyFit: ARP %xip -> %xip\n", FreeRTOS_ntohl( xIPAddressFrom.ulIP_IPv4 ), FreeRTOS_ntohl( xIPAddressTo.ulIP_IPv4 ) ) ); + FreeRTOS_printf( ( "pxEasyFit: ARP %xip -> %xip\n", ( unsigned ) FreeRTOS_ntohl( xIPAddressFrom.ulIP_IPv4 ), ( unsigned ) FreeRTOS_ntohl( xIPAddressTo.ulIP_IPv4 ) ) ); } else /* ipIPv4_FRAME_TYPE */ { diff --git a/source/FreeRTOS_Sockets.c b/source/FreeRTOS_Sockets.c index 29f04c946f..5daa8c1bd2 100644 --- a/source/FreeRTOS_Sockets.c +++ b/source/FreeRTOS_Sockets.c @@ -5505,7 +5505,7 @@ BaseType_t xSocketValid( const ConstSocket_t xSocket ) ( void ) snprintf( pcRemoteIp, sizeof( pcRemoteIp ), "%xip", ( unsigned ) pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4 ); } - FreeRTOS_printf( ( "TCP %5u %-*s:%-16xip:%5u %d/%d %-13.13s %6u %6u%s\n", + FreeRTOS_printf( ( "TCP %5d %-*s:%5d %d/%d %-13.13s %6lu %6u%s\n", pxSocket->usLocalPort, /* Local port on this machine */ xIPWidth, pcRemoteIp, /* IP address of remote machine */ diff --git a/source/FreeRTOS_TCP_IP.c b/source/FreeRTOS_TCP_IP.c index b3936dc1ec..3b8531c384 100644 --- a/source/FreeRTOS_TCP_IP.c +++ b/source/FreeRTOS_TCP_IP.c @@ -497,9 +497,27 @@ { if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) ) { - FreeRTOS_debug_printf( ( "Socket %u -> %xip:%u State %s->%s\n", + char pcBuffer[ 40 ]; + + if( pxSocket->bits.bIsIPv6 != 0 ) + { + FreeRTOS_inet_ntop( FREERTOS_AF_INET6, + pxSocket->u.xTCP.xRemoteIP.xIP_IPv6.ucBytes, + pcBuffer, + sizeof( pcBuffer ) ); + } + else + { + uint32_t ulIPAddress = FreeRTOS_ntohl( pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4 ); + FreeRTOS_inet_ntop( FREERTOS_AF_INET4, + ( const uint8_t * ) &ulIPAddress, + pcBuffer, + sizeof( pcBuffer ) ); + } + + FreeRTOS_debug_printf( ( "Socket %u -> [%s]:%u State %s->%s\n", pxSocket->usLocalPort, - ( unsigned ) pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4, + pcBuffer, pxSocket->u.xTCP.usRemotePort, FreeRTOS_GetTCPStateName( ( UBaseType_t ) xPreviousState ), FreeRTOS_GetTCPStateName( ( UBaseType_t ) eTCPState ) ) ); diff --git a/source/FreeRTOS_TCP_Transmission_IPV4.c b/source/FreeRTOS_TCP_Transmission_IPV4.c index 3b5765bf1c..d783cc0727 100644 --- a/source/FreeRTOS_TCP_Transmission_IPV4.c +++ b/source/FreeRTOS_TCP_Transmission_IPV4.c @@ -502,11 +502,22 @@ /* coverity[misra_c_2012_rule_11_3_violation] */ TCPPacket_t * pxTCPPacket = ( ( TCPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); const uint32_t ulSendLength = - ( uxIPHeaderSizePacket( pxNetworkBuffer ) + ipSIZE_OF_TCP_HEADER ); /* Plus 0 options. */ + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER; /* Plus 0 options. */ + uint8_t ucFlagsReceived = pxTCPPacket->xTCPHeader.ucTCPFlags; pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags; pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER ) << 2; + if( ( ucFlagsReceived & tcpTCP_FLAG_SYN ) != 0U ) + { + /* A synchronise packet is received. It counts as 1 pseudo byte of data, + * so increase the variable with 1. Before sending a reply, the values of + * 'ulSequenceNumber' and 'ulAckNr' will be swapped. */ + uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber ); + ulSequenceNumber++; + pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( ulSequenceNumber ); + } + prvTCPReturnPacket( NULL, pxNetworkBuffer, ulSendLength, pdFALSE ); } #endif /* !ipconfigIGNORE_UNKNOWN_PACKETS */ diff --git a/source/FreeRTOS_TCP_Transmission_IPV6.c b/source/FreeRTOS_TCP_Transmission_IPV6.c index 11beb03e26..65087c8ec2 100644 --- a/source/FreeRTOS_TCP_Transmission_IPV6.c +++ b/source/FreeRTOS_TCP_Transmission_IPV6.c @@ -505,16 +505,26 @@ #else { /* Map the ethernet buffer onto the TCPPacket_t struct for easy access to the fields. */ - uint32_t ulSendLength = ( ipSIZE_OF_IPv6_HEADER + ipSIZE_OF_TCP_HEADER ); /* Plus 0 options. */ + /* MISRA Ref 11.3.1 [Misaligned access] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ /* coverity[misra_c_2012_rule_11_3_violation] */ - TCPPacket_IPv6_t * pxTCPPacket_IPv6 = ( ( TCPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); + TCPPacket_IPv6_t * pxTCPPacket = ( ( TCPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); + const uint32_t ulSendLength = + ipSIZE_OF_IPv6_HEADER + ipSIZE_OF_TCP_HEADER; /* Plus 0 options. */ + + uint8_t ucFlagsReceived = pxTCPPacket->xTCPHeader.ucTCPFlags; + pxTCPPacket->xTCPHeader.ucTCPFlags = ucTCPFlags; + pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER ) << 2; - if( pxTCPPacket_IPv6->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE ) + if( ( ucFlagsReceived & tcpTCP_FLAG_SYN ) != 0U ) { - pxTCPPacket_IPv6->xTCPHeader.ucTCPFlags = ucTCPFlags; - pxTCPPacket_IPv6->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER ) << 2; + /* A synchronise packet is received. It counts as 1 pseudo byte of data, + * so increase the variable with 1. Before sending a reply, the values of + * 'ulSequenceNumber' and 'ulAckNr' will be swapped. */ + uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber ); + ulSequenceNumber++; + pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( ulSequenceNumber ); } prvTCPReturnPacket( NULL, pxNetworkBuffer, ulSendLength, pdFALSE ); diff --git a/source/FreeRTOS_UDP_IPv6.c b/source/FreeRTOS_UDP_IPv6.c index de92a28da9..0684ee954d 100644 --- a/source/FreeRTOS_UDP_IPv6.c +++ b/source/FreeRTOS_UDP_IPv6.c @@ -414,7 +414,10 @@ BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetwork configASSERT( pxNetworkBuffer != NULL ); configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL ); - UDPPacket_IPv6_t * pxUDPPacket_IPv6; + /* When refreshing the ARP/ND cache with received UDP packets we must be + * careful; hundreds of broadcast messages may pass and if we're not + * handling them, no use to fill the cache with those IP addresses. */ + UDPPacket_IPv6_t * pxUDPPacket_IPv6 = ( ( UDPPacket_IPv6_t* ) pxNetworkBuffer->pucEthernetBuffer ); /* Caller must check for minimum packet size. */ pxSocket = pxUDPSocketLookup( usPort ); @@ -425,20 +428,17 @@ BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetwork { if( pxSocket != NULL ) { - if( *ipLOCAL_IP_ADDRESS_POINTER != 0U ) - { - /* When refreshing the ARP/ND cache with received UDP packets we must be - * careful; hundreds of broadcast messages may pass and if we're not - * handling them, no use to fill the ARP cache with those IP addresses. */ - pxUDPPacket_IPv6 = ( ( UDPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); - vNDRefreshCacheEntry( &( pxUDPPacket_IPv6->xEthernetHeader.xSourceAddress ), &( pxUDPPacket_IPv6->xIPHeader.xSourceAddress ), - pxNetworkBuffer->pxEndPoint ); - } - else + if( xCheckRequiresARPResolution( pxNetworkBuffer ) == pdTRUE ) { - /* During DHCP, IP address is not assigned and therefore ARP verification - * is not possible. */ + /* Mark this packet as waiting for ARP resolution. */ + *pxIsWaitingForARPResolution = pdTRUE; + + /* Return a fail to show that the frame will not be processed right now. */ + xReturn = pdFAIL; + break; } + vNDRefreshCacheEntry( &( pxUDPPacket_IPv6->xEthernetHeader.xSourceAddress ), &( pxUDPPacket_IPv6->xIPHeader.xSourceAddress ), + pxNetworkBuffer->pxEndPoint ); #if ( ipconfigUSE_CALLBACKS == 1 ) { From ef5b5623276116aeed8a94994d237824a0e8f7d4 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 22 Feb 2023 15:08:15 +0800 Subject: [PATCH 3/8] In FreeRTOS_DNS_Parser.c : use 'ipUDP_PAYLOAD_OFFSET_IPv4' in stead of 'ipIP_PAYLOAD_OFFSET' --- source/FreeRTOS_DNS_Parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/FreeRTOS_DNS_Parser.c b/source/FreeRTOS_DNS_Parser.c index b868785eda..ab40196beb 100644 --- a/source/FreeRTOS_DNS_Parser.c +++ b/source/FreeRTOS_DNS_Parser.c @@ -452,7 +452,7 @@ } uxUDPOffset = ( size_t ) ( pucUDPPayloadBuffer - pxNetworkBuffer->pucEthernetBuffer ); - configASSERT( ( uxUDPOffset == ipIP_PAYLOAD_OFFSET ) || ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv6 ) ); + configASSERT( ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv4 ) || ( uxUDPOffset == ipUDP_PAYLOAD_OFFSET_IPv6 ) ); if( pxNetworkBuffer->pxEndPoint == NULL ) { From 0b661bf0cefea3645abdfa3a1063f2fc6a2ad213 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 22 Feb 2023 22:36:08 +0800 Subject: [PATCH 4/8] And a few more corrections --- source/FreeRTOS_DNS_Networking.c | 2 +- source/FreeRTOS_IPv6.c | 2 +- source/FreeRTOS_Routing.c | 172 +++---------------------------- source/FreeRTOS_UDP_IP.c | 4 +- source/FreeRTOS_UDP_IPv6.c | 1 + 5 files changed, 20 insertions(+), 161 deletions(-) diff --git a/source/FreeRTOS_DNS_Networking.c b/source/FreeRTOS_DNS_Networking.c index d99b7c5a58..46211cfa3c 100644 --- a/source/FreeRTOS_DNS_Networking.c +++ b/source/FreeRTOS_DNS_Networking.c @@ -154,7 +154,7 @@ if( xReturn <= 0 ) { /* 'pdFREERTOS_ERRNO_EWOULDBLOCK' is returned in case of a timeout. */ - FreeRTOS_printf( ( "DNS_ReadReply returns %d\n", xReturn ) ); + FreeRTOS_printf( ( "DNS_ReadReply returns %d\n", ( int ) xReturn ) ); } return xReturn; diff --git a/source/FreeRTOS_IPv6.c b/source/FreeRTOS_IPv6.c index 579ad884fa..8e573dd25c 100644 --- a/source/FreeRTOS_IPv6.c +++ b/source/FreeRTOS_IPv6.c @@ -166,7 +166,7 @@ eFrameProcessingResult_t prvAllowIPPacketIPv6( const IPHeader_IPv6_t * const pxI const IPv6_Address_t * pxDestinationIPAddress = &( pxIPv6Header->xDestinationAddress ); /* Is the packet for this IP address? */ - if( ( FreeRTOS_FindEndPointOnIP_IPv6( pxDestinationIPAddress ) != NULL ) || + if( ( pxNetworkBuffer->pxEndPoint != NULL ) || /* Is it the multicast address FF00::/8 ? */ ( xIsIPv6Multicast( pxDestinationIPAddress ) != pdFALSE ) || /* Or (during DHCP negotiation) we have no IP-address yet? */ diff --git a/source/FreeRTOS_Routing.c b/source/FreeRTOS_Routing.c index 52b58874fe..2e46625640 100644 --- a/source/FreeRTOS_Routing.c +++ b/source/FreeRTOS_Routing.c @@ -728,7 +728,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, { BaseType_t xSameMACAddress = ( memcmp( pxEndPoint->xMACAddress.ucBytes, pxMACAddress->ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) ? pdTRUE : pdFALSE; - if( xIsIPv6 == ( uint32_t ) pxEndPoint->bits.bIPv6 ) + if( xIsIPv6 == ( BaseType_t ) pxEndPoint->bits.bIPv6 ) { pxFound[ rMATCH_IP_TYPE ] = pxEndPoint; xCount[ rMATCH_IP_TYPE ]++; @@ -736,17 +736,20 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, if( xIsIPv6 != 0 ) { IPv6_Type_t xEndpointType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - BaseType_t xEndpointGlobal = ( xEndpointType == eIPv6_Global ) ? pdTRUE : pdFALSE; - - if( ( memcmp( pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) ) - { - pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; - xCount[ rMATCH_IP_ADDR ]++; - } - else if( xTargetGlobal == xEndpointGlobal ) + if( xEndpointType != eIPv6_Unknown ) { - pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; - xCount[ rMATCH_IP_ADDR ]++; + BaseType_t xEndpointGlobal = ( xEndpointType == eIPv6_Global ) ? pdTRUE : pdFALSE; + + if( ( memcmp( pxEndPoint->ipv6_settings.xIPAddress.ucBytes, pxIPAddressTo->xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) == 0 ) ) + { + pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; + xCount[ rMATCH_IP_ADDR ]++; + } + else if( xTargetGlobal == xEndpointGlobal ) + { + pxFound[ rMATCH_IP_ADDR ] = pxEndPoint; + xCount[ rMATCH_IP_ADDR ]++; + } } } else @@ -898,150 +901,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, &xIPAddressTo, &xMACAddress ); - if( pxEndPoint ) - { - return pxEndPoint; - } - } - - /* _HT_ It is my intention to remove the rest of the code, - * because when pxEasyFit() returns NULL, the packet can not be handled. */ - - /* Probably an ARP packet or a broadcast. */ - switch( pxPacket->xUDPPacket.xEthernetHeader.usFrameType ) - { - #if ( ipconfigUSE_IPv6 != 0 ) - case ipIPv6_FRAME_TYPE: - { - IPv6_Type_t eMyType; - IPv6_Type_t eIPType = xIPv6_GetIPType( &( pxIPPacket_IPv6->xIPHeader.xSourceAddress ) ); - pxEndPoint = pxNetworkEndPoints; - - for( pxEndPoint = FreeRTOS_FirstEndPoint( pxNetworkInterface ); - pxEndPoint != NULL; - pxEndPoint = FreeRTOS_NextEndPoint( pxNetworkInterface, pxEndPoint ) ) - { - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - eMyType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - if( eMyType == eIPType ) - { - break; - } - } - } - - #if ( ipconfigUSE_LLMNR != 0 ) - { - if( pxEndPoint == NULL ) - { - if( xCompareIPv6_Address( &( ipLLMNR_IP_ADDR_IPv6 ), &( pxIPPacket_IPv6->xIPHeader.xDestinationAddress ), ( size_t ) 8U * ipSIZE_OF_IPv6_ADDRESS ) == 0 ) - { - pxEndPoint = FreeRTOS_FirstEndPoint_IPv6( pxNetworkInterface ); - } - } - } - #endif - } - break; - #endif /* ipconfigUSE_IPv6 */ - case ipARP_FRAME_TYPE: - pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress, 3U ); - name = "ARP"; - break; - - case ipIPv4_FRAME_TYPE: - { - /* An IPv4 UDP or TCP packet. */ - uint32_t ulIPSourceAddress = pxPacket->xUDPPacket.xIPHeader.ulSourceIPAddress; - uint32_t ulIPTargetAddress = pxPacket->xUDPPacket.xIPHeader.ulDestinationIPAddress; - uint32_t ulMatchAddress; - BaseType_t xIPBroadcast; - BaseType_t xDone = pdFALSE; - - if( ( FreeRTOS_ntohl( ulIPTargetAddress ) & 0xffuL ) == 0xffuL ) - { - xIPBroadcast = pdTRUE; - } - else - { - xIPBroadcast = pdFALSE; - } - - if( pxPacket->xUDPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) - { - name = "UDP"; - } - else - { - name = "TCP"; - } - - if( ulIPTargetAddress == ~0U ) - { - ulMatchAddress = ulIPSourceAddress; - } - else - { - ulMatchAddress = ulIPTargetAddress; - } - - for( pxEndPoint = FreeRTOS_FirstEndPoint( pxNetworkInterface ); - pxEndPoint != NULL; - pxEndPoint = FreeRTOS_NextEndPoint( pxNetworkInterface, pxEndPoint ) ) - { - ( void ) name; - #if ( ipconfigUSE_IPv6 != 0 ) - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - continue; - } - #endif /* ( ipconfigUSE_IPv6 != 0 ) */ - - if( pxEndPoint->ipv4_settings.ulIPAddress == ulIPTargetAddress ) - { - /* The perfect match. */ - xDone = pdTRUE; - } - else - if( ( xIPBroadcast != pdFALSE ) && - ( ( ( pxEndPoint->ipv4_settings.ulIPAddress ^ ulMatchAddress ) & pxEndPoint->ipv4_settings.ulNetMask ) == 0U ) ) - { - xDone = pdTRUE; - } - else - if( xIsIPv4Multicast( ulIPTargetAddress ) != pdFALSE ) - { - /* Target is a multicast address. */ - xDone = pdTRUE; - } - else - { - /* This end-point doesn't match with the packet. */ - } - - if( xDone != pdFALSE ) - { - break; - } - } - - if( ( xIPBroadcast != 0 ) && ( pxEndPoint == NULL ) ) - { - pxEndPoint = FreeRTOS_FirstEndPoint( pxNetworkInterface ); } - } - break; - - default: - /* Frame type not supported. */ - FreeRTOS_printf( ( "Frametpye %04x not supported.\n", FreeRTOS_ntohs( pxPacket->xUDPPacket.xEthernetHeader.usFrameType ) ) ); - break; - } /* switch usFrameType */ - - ( void ) name; - return pxEndPoint; } /*-----------------------------------------------------------*/ @@ -1070,7 +930,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, if( ( xIPType == ( BaseType_t ) ipTYPE_IPv6 ) && ( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) ) { /* Check if the IP-address is non-zero. */ - if( memcmp( in6addr_any.ucBytes, pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) /* access to ipv6_settings is checked. */ + if( memcmp( in6addr_any.ucBytes, pxEndPoint->ipv6_settings.xGatewayAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) { break; } @@ -1078,7 +938,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, else if( ( xIPType == ( BaseType_t ) ipTYPE_IPv4 ) && ( pxEndPoint->bits.bIPv6 == pdFALSE_UNSIGNED ) ) { - if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) /* access to ipv4_settings is checked. */ + if( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) { break; } diff --git a/source/FreeRTOS_UDP_IP.c b/source/FreeRTOS_UDP_IP.c index 5c1791e7bf..186ab7450d 100644 --- a/source/FreeRTOS_UDP_IP.c +++ b/source/FreeRTOS_UDP_IP.c @@ -263,6 +263,7 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t * pxNetworkBuffe uint16_t usPort, BaseType_t * pxIsWaitingForARPResolution ) { + /* Returning pdPASS means that the packet was consumed, released. */ BaseType_t xReturn = pdFAIL; FreeRTOS_Socket_t * pxSocket; @@ -276,9 +277,6 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t * pxNetworkBuffe /* coverity[misra_c_2012_rule_11_3_violation] */ const UDPPacket_t * pxUDPPacket = ( ( const UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); - /* Caller must check for minimum packet size. */ - pxSocket = pxUDPSocketLookup( usPort ); - if( pxUDPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) { xReturn = xProcessReceivedUDPPacket_IPv4( pxNetworkBuffer, diff --git a/source/FreeRTOS_UDP_IPv6.c b/source/FreeRTOS_UDP_IPv6.c index 0684ee954d..d3c0bfd07e 100644 --- a/source/FreeRTOS_UDP_IPv6.c +++ b/source/FreeRTOS_UDP_IPv6.c @@ -409,6 +409,7 @@ BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetwork uint16_t usPort, BaseType_t * pxIsWaitingForARPResolution ) { + /* Returning pdPASS means that the packet was consumed, released. */ BaseType_t xReturn = pdPASS; FreeRTOS_Socket_t * pxSocket; From 08b6769e8a4e619a9453ed2f15c2faa745b99121 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 22 Feb 2023 22:41:39 +0800 Subject: [PATCH 5/8] Changes to WinPCap network interface, removed debugging code --- .../WinPCap/NetworkInterface.c | 207 ++++++------------ 1 file changed, 67 insertions(+), 140 deletions(-) diff --git a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c index 4488f3de1c..d149644b6c 100644 --- a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c +++ b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c @@ -79,7 +79,6 @@ DWORD WINAPI prvWinPcapSendThread( void * pvParam ); */ static NetworkInterface_t * pxMyInterface; - /* * Print out a numbered list of network interfaces that are available on the * host computer. @@ -90,14 +89,17 @@ static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ); * Open the network interface. The number of the interface to be opened is set * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. */ -static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces ); -static int prvOpenInterface( const char * pucName ); +static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces, + const NetworkInterface_t * pxInterface ); + +static int prvOpenInterface( const char * pucName, + const NetworkInterface_t * pxInterface ); /* * Configure the capture filter to allow blocking reads, and to filter out * packets that are not of interest to this demo. */ -static void prvConfigureCaptureBehaviour( void ); +static void prvConfigureCaptureBehaviour( const NetworkInterface_t * pxInterface ); /* * A function that simulates Ethernet interrupts by periodically polling the @@ -197,7 +199,7 @@ static BaseType_t xWinPcap_NetworkInterfaceInitialise( NetworkInterface_t * pxIn * the interface could not be opened. */ if( pxAllNetworkInterfaces != NULL ) { - prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces ); + prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces, pxInterface ); } if( pxOpenedInterfaceHandle != NULL ) @@ -342,9 +344,22 @@ static BaseType_t xWinPcap_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) return xResult; } - /*-----------------------------------------------------------*/ +#if ( ipconfigCOMPATIBLE_WITH_SINGLE != 0 ) + + +/* Do not call the following function directly. It is there for downward compatibility. + * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point + * objects. See the description in FreeRTOS_Routing.h. */ + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) + { + pxWinPcap_FillInterfaceDescriptor( xEMACIndex, pxInterface ); + } + +#endif /* ( ipconfigCOMPATIBLE_WITH_SINGLE != 0 ) */ +/*-----------------------------------------------------------*/ NetworkInterface_t * pxWinPcap_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) @@ -380,7 +395,8 @@ NetworkInterface_t * pxWinPcap_FillInterfaceDescriptor( BaseType_t xEMACIndex, * adapters, the numbering of interfaces changes all the time. * The new macro 'configNETWORK_INTERFACE_TYPE_TO_USE' can be * used to define the name of the interface to use, e.g. "Realtek" - * Note that a sort of strcasestr() is used. + * Note that a sort of strcasestr() is used to find a match between + * an interface name and e.g. "Realtek". */ static BaseType_t xDesiredAdapter( const char * pcDescription ) { @@ -494,7 +510,8 @@ static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) } /*-----------------------------------------------------------*/ -static int prvOpenInterface( const char * pucName ) +static int prvOpenInterface( const char * pucName, + const NetworkInterface_t * pxInterface ) { static char pucInterfaceName[ 256 ]; @@ -526,28 +543,29 @@ static int prvOpenInterface( const char * pucName ) { /* Configure the capture filter to allow blocking reads, and to filter * out packets that are not of interest to this demo. */ - prvConfigureCaptureBehaviour(); + prvConfigureCaptureBehaviour( pxInterface ); } return 0; } /*-----------------------------------------------------------*/ -static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces ) +static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces, + const NetworkInterface_t * pxInterface ) { - pcap_if_t * pxInterface; + pcap_if_t * pxPCAPInterface; int32_t x; /* Walk the list of devices until the selected device is located. */ - pxInterface = pxAllNetworkInterfaces; + pxPCAPInterface = pxAllNetworkInterfaces; for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ ) { - pxInterface = pxInterface->next; + pxPCAPInterface = pxPCAPInterface->next; } /* Open the selected interface. */ - if( prvOpenInterface( pxInterface->name ) == 0 ) + if( prvOpenInterface( pxPCAPInterface->name, pxInterface ) == 0 ) { printf( "Successfully opened interface number %d.\n", x + 1 ); } @@ -561,16 +579,26 @@ static void prvOpenSelectedNetworkInterface( pcap_if_t * pxAllNetworkInterfaces } /*-----------------------------------------------------------*/ -static void prvConfigureCaptureBehaviour( void ) +static void prvConfigureCaptureBehaviour( const NetworkInterface_t * pxInterface ) { struct bpf_program xFilterCode; uint32_t ulNetMask; + const uint8_t * pucMAC; + NetworkEndPoint_t * pxEndPoint; + + /* Find the MAC address of the very first end-point. */ + pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + + /* Make sure that at least one end-point is defined. */ + configASSERT( pxEndPoint != NULL ); + + pucMAC = pxEndPoint->xMACAddress.ucBytes; /* Set up a filter so only the packets of interest are passed to the IP * stack. cErrorBuffer is used for convenience to create the string. Don't * confuse this with an error message. */ - sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x", - ipLOCAL_MAC_ADDRESS[ 0 ], ipLOCAL_MAC_ADDRESS[ 1 ], ipLOCAL_MAC_ADDRESS[ 2 ], ipLOCAL_MAC_ADDRESS[ 3 ], ipLOCAL_MAC_ADDRESS[ 4 ], ipLOCAL_MAC_ADDRESS[ 5 ] ); + snprintf( cErrorBuffer, sizeof( cErrorBuffer ), "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x", + pucMAC[ 0 ], pucMAC[ 1 ], pucMAC[ 2 ], pucMAC[ 3 ], pucMAC[ 4 ], pucMAC[ 5 ] ); ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0; @@ -755,8 +783,6 @@ static BaseType_t xPacketBouncedBack( const uint8_t * pucBuffer ) } /*-----------------------------------------------------------*/ -extern NetworkEndPoint_t * pxGetEndpoint( BaseType_t xIPType ); - static void prvInterruptSimulatorTask( void * pvParameters ) { struct pcap_pkthdr xHeader; @@ -799,12 +825,14 @@ static void prvInterruptSimulatorTask( void * pvParameters ) /* Will the data fit into the frame buffer? */ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE ) { + BaseType_t xBounced = xPacketBouncedBack( pucPacketData ); + /* Obtain a buffer into which the data can be placed. This * is only an interrupt simulator, not a real interrupt, so it * is ok to call the task level function here, but note that * some buffer implementations cannot be called from a real * interrupt. */ - if( xPacketBouncedBack( pucPacketData ) == pdFALSE ) + if( xBounced == pdFALSE ) { pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 ); } @@ -831,129 +859,28 @@ static void prvInterruptSimulatorTask( void * pvParameters ) pxNetworkBuffer->pxInterface = pxMyInterface; pxNetworkBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxNetworkBuffer->pucEthernetBuffer ); - /*if( pxNetworkBuffer->pxEndPoint == NULL ) */ + /* Just for now, make sure that there is a valid end-point. */ + if(pxNetworkBuffer->pxEndPoint == NULL) { - char pcDescription[ 129 ] = "unknown"; - const EthernetHeader_t * pxEthernetHeader = ( ( const EthernetHeader_t * ) pxNetworkBuffer->pucEthernetBuffer ); - uint8_t ucType = ipTYPE_IPv4; - - switch( pxEthernetHeader->usFrameType ) - { - case ipARP_FRAME_TYPE: - { - const ProtocolPacket_t * pxPacket = ( ( const ProtocolPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); - snprintf( pcDescription, sizeof pcDescription, "ARP frame for %xip", - FreeRTOS_ntohl( pxPacket->xARPPacket.xARPHeader.ulTargetProtocolAddress ) ); - } - break; - - case ipPROTOCOL_ICMP: - snprintf( pcDescription, sizeof pcDescription, "ICMP frame" ); - break; - - case ipIPv4_FRAME_TYPE: - { - const IPPacket_t * pxIPPacket; - uint8_t ucProtocol; - pxIPPacket = ( const IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; - ucProtocol = pxIPPacket->xIPHeader.ucProtocol; - - if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) - { - const ProtocolHeaders_t * pxProtocolHeaders = ( ( const ProtocolHeaders_t * ) - &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizePacket( pxNetworkBuffer ) ] ) ); - uint32_t ulLocalIP, ulRemoteIP; - uint16_t usLocalPort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usDestinationPort ); - uint16_t usRemotePort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usSourcePort ); - const IPHeader_t * pxIPHeader; - pxIPHeader = ( ( const IPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) ); - ulLocalIP = FreeRTOS_htonl( pxIPHeader->ulDestinationIPAddress ); - ulRemoteIP = FreeRTOS_htonl( pxIPHeader->ulSourceIPAddress ); - - snprintf( pcDescription, sizeof pcDescription, "TCP v4 packet %xip port%u to %xip: port %u", - ulRemoteIP, usRemotePort, ulLocalIP, usLocalPort ); - } - else if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) - { - snprintf( pcDescription, sizeof pcDescription, "UDP v4 packet" ); - const UDPPacket_t * pxUDPPacket = ( ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); - - if( pxUDPPacket->xIPHeader.ulSourceIPAddress == 0x642c6276U ) - { - FreeRTOS_printf( ( "Received UDP packet from %xip\n", - ( unsigned ) ( FreeRTOS_htonl( pxUDPPacket->xIPHeader.ulSourceIPAddress ) ) ) ); - } - } - else - { - snprintf( pcDescription, sizeof pcDescription, "v4 packet protocol %02X", ucProtocol ); - } - } - break; - - case ipIPv6_FRAME_TYPE: - { - const IPHeader_IPv6_t * pxIPHeader_IPv6; - uint8_t ucProtocol; - - ucType = ipTYPE_IPv6; - pxIPHeader_IPv6 = ( const IPHeader_IPv6_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ); - - ucProtocol = pxIPHeader_IPv6->ucNextHeader; - - if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP ) - { - snprintf( pcDescription, sizeof pcDescription, "TCP v6 packet" ); - } - else if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) - { - snprintf( pcDescription, sizeof pcDescription, "UDP v6 packet" ); - } - else if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP_IPv6 ) - { - snprintf( pcDescription, sizeof pcDescription, "ICMP v6 packet" ); - } - else - { - snprintf( pcDescription, sizeof pcDescription, "v6 packet protocol %02X", ucProtocol ); - } - } - break; - - default: - snprintf( pcDescription, sizeof pcDescription, "Unknown frame %04x", pxEthernetHeader->usFrameType ); - break; - } - - if( pxNetworkBuffer->pxEndPoint == NULL ) - { - pxNetworkBuffer->pxEndPoint = pxGetEndpoint( ucType ); - - if( strncasecmp( "ARP", pcDescription, 3 ) != 0 ) - { - FreeRTOS_printf( ( "No end-point for \"%s\". Using 0x%p type IPv%d\n", - pcDescription, - pxNetworkBuffer->pxEndPoint, - ucType == ipTYPE_IPv6 ? 6 : 4 ) ); - } - - /* pxNetworkBuffer->pxEndPoint = FreeRTOS_FirstEndPoint( pxMyInterface ); / *temporary change for single end point * / */ - } + FreeRTOS_printf( ( "Network interface: dropped packet\n" ) ); + vReleaseNetworkBufferAndDescriptor( BUFFER_FROM_WHERE_CALL( 153 ) pxNetworkBuffer ); } - - /* Data was received and stored. Send a message to - * the IP task to let it know. */ - if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) + else { - /* The buffer could not be sent to the stack so - * must be released again. This is only an - * interrupt simulator, not a real interrupt, so it - * is ok to use the task level function here, but - * note no all buffer implementations will allow - * this function to be executed from a real - * interrupt. */ - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - iptraceETHERNET_RX_EVENT_LOST(); + /* Data was received and stored. Send a message to + * the IP task to let it know. */ + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) + { + /* The buffer could not be sent to the stack so + * must be released again. This is only an + * interrupt simulator, not a real interrupt, so it + * is ok to use the task level function here, but + * note no all buffer implementations will allow + * this function to be executed from a real + * interrupt. */ + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + iptraceETHERNET_RX_EVENT_LOST(); + } } } else From 7a3958a507dfc6a0b6194ad429c64c84954c91b0 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Thu, 23 Feb 2023 13:28:30 +0800 Subject: [PATCH 6/8] After applying uncrustify --- source/FreeRTOS_ARP.c | 2 +- source/FreeRTOS_Routing.c | 4 ++-- source/FreeRTOS_UDP_IPv4.c | 1 + source/FreeRTOS_UDP_IPv6.c | 4 +++- source/portable/NetworkInterface/WinPCap/NetworkInterface.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/source/FreeRTOS_ARP.c b/source/FreeRTOS_ARP.c index d47a33f93d..02b08e46a1 100644 --- a/source/FreeRTOS_ARP.c +++ b/source/FreeRTOS_ARP.c @@ -542,7 +542,7 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw else { /* MISRA Ref 11.3.1 [Misaligned access] */ - /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ /* coverity[misra_c_2012_rule_11_3_violation] */ const IPPacket_t * pxIPPacket = ( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer ); const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader ); diff --git a/source/FreeRTOS_Routing.c b/source/FreeRTOS_Routing.c index 2e46625640..37fb3c99a0 100644 --- a/source/FreeRTOS_Routing.c +++ b/source/FreeRTOS_Routing.c @@ -736,6 +736,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, if( xIsIPv6 != 0 ) { IPv6_Type_t xEndpointType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + if( xEndpointType != eIPv6_Unknown ) { BaseType_t xEndpointGlobal = ( xEndpointType == eIPv6_Global ) ? pdTRUE : pdFALSE; @@ -900,8 +901,7 @@ void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface, &xIPAddressFrom, &xIPAddressTo, &xMACAddress ); - - } + } return pxEndPoint; } /*-----------------------------------------------------------*/ diff --git a/source/FreeRTOS_UDP_IPv4.c b/source/FreeRTOS_UDP_IPv4.c index d0a557074c..54d3891829 100644 --- a/source/FreeRTOS_UDP_IPv4.c +++ b/source/FreeRTOS_UDP_IPv4.c @@ -297,6 +297,7 @@ void vProcessGeneratedUDPPacket_IPv4( NetworkBufferDescriptor_t * const pxNetwor } #endif /* if( ipconfigETHERNET_MINIMUM_PACKET_BYTES > 0 ) */ iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer ); + if( ( pxInterface != NULL ) && ( pxInterface->pfOutput != NULL ) ) { ( void ) pxInterface->pfOutput( pxInterface, pxNetworkBuffer, pdTRUE ); diff --git a/source/FreeRTOS_UDP_IPv6.c b/source/FreeRTOS_UDP_IPv6.c index d3c0bfd07e..2b6498d651 100644 --- a/source/FreeRTOS_UDP_IPv6.c +++ b/source/FreeRTOS_UDP_IPv6.c @@ -415,10 +415,11 @@ BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetwork configASSERT( pxNetworkBuffer != NULL ); configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL ); + /* When refreshing the ARP/ND cache with received UDP packets we must be * careful; hundreds of broadcast messages may pass and if we're not * handling them, no use to fill the cache with those IP addresses. */ - UDPPacket_IPv6_t * pxUDPPacket_IPv6 = ( ( UDPPacket_IPv6_t* ) pxNetworkBuffer->pucEthernetBuffer ); + UDPPacket_IPv6_t * pxUDPPacket_IPv6 = ( ( UDPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); /* Caller must check for minimum packet size. */ pxSocket = pxUDPSocketLookup( usPort ); @@ -438,6 +439,7 @@ BaseType_t xProcessReceivedUDPPacket_IPv6( NetworkBufferDescriptor_t * pxNetwork xReturn = pdFAIL; break; } + vNDRefreshCacheEntry( &( pxUDPPacket_IPv6->xEthernetHeader.xSourceAddress ), &( pxUDPPacket_IPv6->xIPHeader.xSourceAddress ), pxNetworkBuffer->pxEndPoint ); diff --git a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c index d149644b6c..81c6f462ef 100644 --- a/source/portable/NetworkInterface/WinPCap/NetworkInterface.c +++ b/source/portable/NetworkInterface/WinPCap/NetworkInterface.c @@ -860,7 +860,7 @@ static void prvInterruptSimulatorTask( void * pvParameters ) pxNetworkBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxNetworkBuffer->pucEthernetBuffer ); /* Just for now, make sure that there is a valid end-point. */ - if(pxNetworkBuffer->pxEndPoint == NULL) + if( pxNetworkBuffer->pxEndPoint == NULL ) { FreeRTOS_printf( ( "Network interface: dropped packet\n" ) ); vReleaseNetworkBufferAndDescriptor( BUFFER_FROM_WHERE_CALL( 153 ) pxNetworkBuffer ); From fd9ecd47e7129ce4eec34189873a1cd748f112c0 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Thu, 23 Feb 2023 13:39:24 +0800 Subject: [PATCH 7/8] Oops, I forgot the push changes in include files. --- source/include/FreeRTOS_DNS_Globals.h | 7 ++++--- source/include/FreeRTOS_DNS_Parser.h | 2 +- source/include/FreeRTOS_IPv6_Private.h | 6 +++--- source/include/FreeRTOS_Routing.h | 5 +++++ source/include/FreeRTOS_Sockets.h | 4 ++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/source/include/FreeRTOS_DNS_Globals.h b/source/include/FreeRTOS_DNS_Globals.h index 3b33dd3409..415270c054 100644 --- a/source/include/FreeRTOS_DNS_Globals.h +++ b/source/include/FreeRTOS_DNS_Globals.h @@ -131,6 +131,7 @@ #else #define ipMDNS_IP_ADDRESS 0xfb0000e0U /* 224.0.0.251 */ #endif + #define ipMDNS_TIME_TO_LIVE 255U #define ipMDNS_PORT 5353U /* Standard mDNS port. */ #define ipLLMNR_PORT 5355 /* Standard LLMNR port. */ #define ipDNS_PORT 53 /* Standard DNS port. */ @@ -219,7 +220,7 @@ struct freertos_addrinfo * pxLastAddress; /**< This variable is used while creating a linked-list of IP-addresses. */ struct freertos_addrinfo ** ppxLastAddress; /**< This variable is also used while creating a linked-list of IP-addresses. */ } ParseSet_t; - #if ( ipconfigUSE_LLMNR == 1 ) + #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 ) #include "pack_struct_start.h" struct xLLMNRAnswer @@ -234,7 +235,7 @@ } #include "pack_struct_end.h" typedef struct xLLMNRAnswer LLMNRAnswer_t; - #endif /* if ( ipconfigUSE_LLMNR == 1 ) */ + #endif /* if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 ) */ #if ( ipconfigUSE_NBNS == 1 ) @@ -310,7 +311,7 @@ BaseType_t xIs_IPv6; /**< pdTRUE if the IPv6 member is used. */ } IPv46_Address_t; - #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) + #if ( ipconfigUSE_MDNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) /* * The following function should be provided by the user and return true if it diff --git a/source/include/FreeRTOS_DNS_Parser.h b/source/include/FreeRTOS_DNS_Parser.h index ec775115dc..cbc0f01751 100644 --- a/source/include/FreeRTOS_DNS_Parser.h +++ b/source/include/FreeRTOS_DNS_Parser.h @@ -69,7 +69,7 @@ /* * The NBNS and the LLMNR protocol share this reply function. */ - #if ( ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) ) + #if ( ( ipconfigUSE_MDNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) ) void prepareReplyDNSMessage( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t lNetLength ); #endif diff --git a/source/include/FreeRTOS_IPv6_Private.h b/source/include/FreeRTOS_IPv6_Private.h index 9841b2bd8f..b356d6cfa6 100644 --- a/source/include/FreeRTOS_IPv6_Private.h +++ b/source/include/FreeRTOS_IPv6_Private.h @@ -224,9 +224,9 @@ typedef struct xIP_PACKET_IPv6 IPPacket_IPv6_t; #include "pack_struct_start.h" struct xICMP_PACKET_IPv6 { - EthernetHeader_t xEthernetHeader; - IPHeader_IPv6_t xIPHeader; - ICMPHeader_IPv6_t xICMPHeaderIPv6; + EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */ + IPHeader_IPv6_t xIPHeader; /* 14 + 40 = 54 */ + ICMPHeader_IPv6_t xICMPHeaderIPv6; /* 54 + 8 = 62 */ } #include "pack_struct_end.h" typedef struct xICMP_PACKET_IPv6 ICMPPacket_IPv6_t; diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index df6e144e01..2b5cfd9150 100755 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -324,6 +324,10 @@ void vSetSocketEndpoint( Socket_t xSocket, NetworkEndPoint_t * pxEndPoint ); + const char* pcEndpointName( const NetworkEndPoint_t* pxEndPoint, + char* pcBuffer, + size_t uxSize ); + typedef enum { eIPv6_Global, /* 001 */ @@ -340,6 +344,7 @@ * @return A value from enum IPv6_Type_t. */ IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress ); + const char * pcEndpointName( const NetworkEndPoint_t * pxEndPoint, char * pcBuffer, size_t uxSize ); diff --git a/source/include/FreeRTOS_Sockets.h b/source/include/FreeRTOS_Sockets.h index e2bf39227f..d67b913424 100644 --- a/source/include/FreeRTOS_Sockets.h +++ b/source/include/FreeRTOS_Sockets.h @@ -553,6 +553,10 @@ #endif /* ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) */ + #include "FreeRTOS_IP_Private.h" + #include "FreeRTOS_IPv4_Sockets.h" + #include "FreeRTOS_IPv6_Sockets.h" + #ifdef __cplusplus } /* extern "C" */ #endif From c111461313e81791b42f91dceffa27517101b66f Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Thu, 23 Feb 2023 17:00:26 +0800 Subject: [PATCH 8/8] Now removing it, hopefully --- tools/tcp_utilities/include/NTPDemo.c | 693 -------------------------- 1 file changed, 693 deletions(-) delete mode 100644 tools/tcp_utilities/include/NTPDemo.c diff --git a/tools/tcp_utilities/include/NTPDemo.c b/tools/tcp_utilities/include/NTPDemo.c deleted file mode 100644 index 13dfbdf382..0000000000 --- a/tools/tcp_utilities/include/NTPDemo.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * FreeRTOS+TCP V2.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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 - */ - -/* - * NTPDemo.c - * - * An example of how to lookup a domain using DNS - * And also how to send and receive UDP messages to get the NTP time - * - */ - -/* Standard includes. */ -#include -#include -#include -#include - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" - -/* FreeRTOS+TCP includes. */ -#include "FreeRTOS_IP.h" -#include "FreeRTOS_Sockets.h" -#include "FreeRTOS_DNS.h" -#include "FreeRTOS_Stream_Buffer.h" - -/* Use the date & time functions from +FAT. */ -#if ( USE_PLUS_FAT != 0 ) - #include "ff_time.h" -#endif /* ( USE_PLUS_FAT != 0 ) */ - -#include "NTPDemo.h" -#include "ntpClient.h" - -#include "date_and_time.h" - -#if ( ipconfigDNS_USE_CALLBACKS == 0 ) - #error ipconfigDNS_USE_CALLBACKS must be 1 -#endif - -#if ( ipconfigMULTI_INTERFACE == 0 ) - #ifndef ipSIZE_OF_IPv4_ADDRESS - #define ipSIZE_OF_IPv4_ADDRESS 4 - #endif - #define FREERTOS_AF_INET4 FREERTOS_AF_INET -#endif - -/* Set time: sets the current time in seconds-after-1/1/1970 - * This function must be provided by the application. */ - -time_t get_time( time_t * puxTime ); -int set_time( const time_t * t ); - -enum EStatus -{ - EStatusLookup, - EStatusAsking, - EStatusPause, - EStatusFailed, -}; - -static struct SNtpPacket xNTPPacket; - -BaseType_t xNTPHasTime; -uint32_t ulNTPTime; - -#if ( ipconfigUSE_CALLBACKS == 0 ) - static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ]; -#endif - -static enum EStatus xStatus = EStatusLookup; - -static const char * pcTimeServers[] = -{ - "0.asia.pool.ntp.org", - "0.europe.pool.ntp.org", - "0.id.pool.ntp.org", - "0.south-america.pool.ntp.org", - "0.oceania.pool.ntp.org", - "0.north-america.pool.ntp.org" -}; - -static SemaphoreHandle_t xNTPWakeupSem = NULL; -static uint32_t ulIPAddressFound; - -#if ( ipconfigUSE_IPv6 != 0 ) - static struct freertos_sockaddr6 xIPAddressFound; -#endif -static BaseType_t xHasIPAddress = pdFALSE; - -static Socket_t xNTP_UDPSocket = NULL; -static TaskHandle_t xNTPTaskhandle = NULL; -static TickType_t uxSendTime; -static BaseType_t xPreferredHostType = FREERTOS_AF_INET4; -static BaseType_t xDNSAsynchronous = pdTRUE; -static BaseType_t xDNSLogging = pdFALSE; - -static void prvNTPTask( void * pvParameters ); - -static void vSignalTask( void ) -{ - #if ( ipconfigUSE_CALLBACKS == 0 ) - if( xNTP_UDPSocket != NULL ) - { - /* Send a signal to the socket so that the - * FreeRTOS_recvfrom will get interrupted. */ - FreeRTOS_SignalSocket( xNTP_UDPSocket ); - } - else - #endif - - if( xNTPWakeupSem != NULL ) - { - xSemaphoreGive( xNTPWakeupSem ); - } -} - -void vNTPClearCache( void ) -{ - ulIPAddressFound = 0U; - #if ( ipconfigUSE_IPv6 != 0 ) - { - memset( &( xIPAddressFound ), 0, sizeof xIPAddressFound ); - } - #endif - xHasIPAddress = pdFALSE; -} - -void vNTPSetNTPType( BaseType_t aIPType, - BaseType_t xAsynchronous, - BaseType_t xLogging ) -{ - switch( aIPType ) - { - case 4: - xPreferredHostType = FREERTOS_AF_INET4; - break; - - #if ( ipconfigUSE_IPv6 != 0 ) - case 6: - xPreferredHostType = FREERTOS_AF_INET6; - break; - #endif - default: - break; - } - - xDNSAsynchronous = xAsynchronous; - xDNSLogging = xLogging; - FreeRTOS_printf( ( "NTP config: Using IPv%d, %ssynchronous with%s logging\n", - ( xPreferredHostType == FREERTOS_AF_INET4 ) ? 4 : 6, - xDNSAsynchronous ? "a" : "", - xDNSLogging ? "" : "out" ) ); -} - -BaseType_t xNTPTaskIsRunning() -{ - BaseType_t xResult = ( xNTPTaskhandle != NULL ) ? pdTRUE : pdFALSE; - - return xResult; -} - -void vStartNTPTask( uint16_t usTaskStackSize, - UBaseType_t uxTaskPriority ) -{ - /* The only public function in this module: start a task to contact - * some NTP server. */ - - if( xNTPTaskhandle != NULL ) - { - switch( xStatus ) - { - case EStatusPause: - xStatus = EStatusAsking; - vSignalTask(); - break; - - case EStatusLookup: - FreeRTOS_printf( ( "NTP looking up server\n" ) ); - break; - - case EStatusAsking: - FreeRTOS_printf( ( "NTP still asking\n" ) ); - break; - - case EStatusFailed: - FreeRTOS_printf( ( "NTP failed somehow\n" ) ); - ulIPAddressFound = 0ul; - xStatus = EStatusLookup; - vSignalTask(); - break; - } - } - else - { - xNTP_UDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); - - if( xNTP_UDPSocket != NULL ) - { - struct freertos_sockaddr xAddress; - #if ( ipconfigUSE_CALLBACKS != 0 ) - BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 ); - #else - BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 ); - #endif - - xAddress.sin_addr = 0ul; - xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); - - FreeRTOS_bind( xNTP_UDPSocket, &xAddress, sizeof( xAddress ) ); - FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); - xTaskCreate( prvNTPTask, /* The function that implements the task. */ - ( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */ - usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ - NULL, /* The task parameter, not used in this case. */ - uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ - &xNTPTaskhandle ); /* The task handle. */ - } - else - { - FreeRTOS_printf( ( "Creating socket failed\n" ) ); - } - } -} -/*-----------------------------------------------------------*/ - -#if ( ipconfigUSE_IPv6 != 0 ) - static void vDNS_callback( const char * pcName, - void * pvSearchID, - struct freertos_addrinfo * pxAddress ) - { - ( void ) pvSearchID; - - if( pxAddress == NULL ) - { - FreeRTOS_printf( ( "vDNS_callback: DNS lookup timed out\n" ) ); - } - else - { - if( pxAddress->ai_family == FREERTOS_AF_INET4 ) - { - char pcBuf[ 16 ]; - - /* The DNS lookup has a result, or it has reached the time-out. */ - ulIPAddressFound = pxAddress->ai_addr->sin_addr; - FreeRTOS_inet_ntoa( ulIPAddressFound, pcBuf ); - FreeRTOS_printf( ( "vDNS_callback: IP address of '%s' found: %s\n", pcName, pcBuf ) ); - - if( ulIPAddressFound != 0U ) - { - memset( xIPAddressFound.sin_addr6.ucBytes, 0, ipSIZE_OF_IPv6_ADDRESS ); - xHasIPAddress = pdTRUE; - xStatus = EStatusAsking; - } - } - else if( pxAddress->ai_family == FREERTOS_AF_INET6 ) - { - /* struct freertos_sockaddr * ai_addr */ - struct freertos_sockaddr6 * sockaddr6 = ( struct freertos_sockaddr6 * ) pxAddress->ai_addr; - - xIPAddressFound.sin_len = sizeof( xIPAddressFound ); /* Ignored, still present for backward compatibility. */ - xIPAddressFound.sin_family = FREERTOS_AF_INET6; /* Set to FREERTOS_AF_INET6. */ - xIPAddressFound.sin_port = FreeRTOS_htons( NTP_PORT ); - xIPAddressFound.sin_flowinfo = 0; /* IPv6 flow information. */ - memcpy( xIPAddressFound.sin_addr6.ucBytes, sockaddr6->sin_addr6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); - - FreeRTOS_printf( ( "vDNS_callback: using address %pip\n", xIPAddressFound.sin_addr6.ucBytes ) ); - ulIPAddressFound = 0U; - xHasIPAddress = pdTRUE; - xStatus = EStatusAsking; - } - else - { - FreeRTOS_printf( ( "vDNS_callback: Unknown address family 0x%02x\n", ( unsigned ) pxAddress->ai_family ) ); - } - } - - vSignalTask(); - } -#else /* if ( ipconfigUSE_IPv6 != 0 ) */ - static void vDNS_callback( const char * pcName, - void * pvSearchID, - uint32_t ulIPAddress ) - { - char pcBuf[ 16 ]; - - /* The DNS lookup has a result, or it has reached the time-out. */ - FreeRTOS_inet_ntoa( ulIPAddress, pcBuf ); - FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) ); - - if( ulIPAddressFound == 0U ) - { - ulIPAddressFound = ulIPAddress; - } - - /* For testing: in case DNS doesn't respond, still try some NTP server - * with a known IP-address. */ - if( ulIPAddressFound != 0U ) - { - xHasIPAddress = pdTRUE; - xStatus = EStatusAsking; - } - - vSignalTask(); - } -#endif /* if ( ipconfigUSE_IPv6 != 0 ) */ -/*-----------------------------------------------------------*/ - -static void prvSwapFields( struct SNtpPacket * pxPacket ) -{ - /* NTP messages are big-endian */ - pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay ); - pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion ); - - pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds ); - pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction ); - - pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds ); - pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction ); - - pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds ); - pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction ); - - pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds ); - pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction ); -} -/*-----------------------------------------------------------*/ - -static void prvNTPPacketInit() -{ - memset( &xNTPPacket, '\0', sizeof( xNTPPacket ) ); - - xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */ - xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */ - xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */ - xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */ - xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */ - - /* use the recorded NTP time */ - time_t uxSecs = get_time( NULL ); /* apTime may be NULL, returns seconds */ - - xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */ - xNTPPacket.transmitTimestamp.seconds = uxSecs + 3; - - /* Transform the contents of the fields from native to big endian. */ - prvSwapFields( &xNTPPacket ); -} -/*-----------------------------------------------------------*/ - -static void prvReadTime( struct SNtpPacket * pxPacket ) -{ - #if ( USE_PLUS_FAT != 0 ) - FF_TimeStruct_t xTimeStruct; - #else - struct tm xTimeStruct; - #endif - - time_t uxPreviousSeconds; - time_t uxPreviousMS; - - time_t uxCurrentSeconds; - time_t uxCurrentMS; - - const char * pcTimeUnit; - int32_t ilDiff; - TickType_t uxTravelTime; - - uxTravelTime = xTaskGetTickCount() - uxSendTime; - - /* Transform the contents of the fields from big to native endian. */ - prvSwapFields( pxPacket ); - - uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970; - uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967; - uxCurrentSeconds += uxCurrentMS / 1000; - uxCurrentMS = uxCurrentMS % 1000; - - /* Get the last time recorded */ - uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS ); - - /* Set the new time with precision in msec. * / */ - FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS ); - - if( uxCurrentSeconds >= uxPreviousSeconds ) - { - ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds ); - } - else - { - ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds ); - } - - if( ( ilDiff < -5 ) || ( ilDiff > 5 ) ) - { - /* More than 5 seconds difference. */ - pcTimeUnit = "sec"; - } - else - { - /* Less than or equal to 5 second difference. */ - pcTimeUnit = "ms"; - uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds; - int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS; - int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS; - ilDiff = iCurMS - iPrevMS; - } - - /*uxCurrentSeconds -= iTimeZone; */ - - #if ( USE_PLUS_FAT != 0 ) - FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct ); - #else - gmtime_r( &uxCurrentSeconds, &xTimeStruct ); - #endif /* ( USE_PLUS_FAT != 0 ) */ - - /* - * 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms) - * 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms) - */ - - FreeRTOS_printf( ( "NTP time: %u/%u/%02u %2u:%02u:%02u.%03u Diff %d %s (%lu ms)\n", - ( unsigned ) xTimeStruct.tm_mday, - ( unsigned ) xTimeStruct.tm_mon + 1, - ( unsigned ) xTimeStruct.tm_year + 1900, - ( unsigned ) xTimeStruct.tm_hour, - ( unsigned ) xTimeStruct.tm_min, - ( unsigned ) xTimeStruct.tm_sec, - ( unsigned ) uxCurrentMS, - ( signed ) ilDiff, - pcTimeUnit, - uxTravelTime ) ); - - xNTPHasTime = pdTRUE; - ulNTPTime = uxCurrentSeconds; - set_time( &uxCurrentSeconds ); - - /* Remove compiler warnings in case FreeRTOS_printf() is not used. */ - ( void ) pcTimeUnit; - ( void ) uxTravelTime; -} -/*-----------------------------------------------------------*/ - -#if ( ipconfigUSE_CALLBACKS != 0 ) - - static BaseType_t xOnUDPReceive( Socket_t xSocket, - void * pvData, - size_t xLength, - const struct freertos_sockaddr * pxFrom, - const struct freertos_sockaddr * pxDest ) - { - ( void ) xSocket; - ( void ) pxFrom; - ( void ) pxDest; - - if( xLength >= sizeof( xNTPPacket ) ) - { - prvReadTime( ( struct SNtpPacket * ) pvData ); - - if( xStatus != EStatusPause ) - { - xStatus = EStatusPause; - } - } - - vSignalTask(); - /* Tell the driver not to store the RX data */ - return 1; - } - /*-----------------------------------------------------------*/ - -#endif /* ipconfigUSE_CALLBACKS != 0 */ - -static void prvNTPTask( void * pvParameters ) -{ - BaseType_t xServerIndex = 3; - struct freertos_sockaddr xAddress; - - #if ( ipconfigUSE_CALLBACKS != 0 ) - F_TCP_UDP_Handler_t xHandler; - #endif /* ipconfigUSE_CALLBACKS != 0 */ - - ( void ) pvParameters; - - xStatus = EStatusLookup; - #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 ) - { - xNTPWakeupSem = xSemaphoreCreateBinary(); - } - #endif - - #if ( ipconfigUSE_CALLBACKS != 0 ) - { - memset( &xHandler, '\0', sizeof( xHandler ) ); - xHandler.pxOnUDPReceive = xOnUDPReceive; - FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) ); - } - #endif - #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) - { - FreeRTOS_setsockopt( xNTP_UDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) ); - } - #endif - - for( ; ; ) - { - switch( xStatus ) - { - case EStatusLookup: - - if( xHasIPAddress == 0 ) - { - char pcServerName[ 64 ]; - - if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) ) - { - xServerIndex = 0; - } - - snprintf( pcServerName, sizeof pcServerName, "%s", pcTimeServers[ xServerIndex ] ); - - if( ( pcServerName[ 0 ] == '0' ) && ( xPreferredHostType == FREERTOS_AF_INET6 ) ) - { - pcServerName[ 0 ] = '2'; - } - - FreeRTOS_printf( ( "Looking up server '%s' IPv%c\n", - pcServerName, - ( xPreferredHostType == FREERTOS_AF_INET4 ) ? '4' : '6' ) ); - #if ( ipconfigMULTI_INTERFACE != 0 ) - struct freertos_addrinfo xHints; - struct freertos_addrinfo * pxResults = NULL; - - memset( &( xHints ), 0, sizeof xHints ); - xHints.ai_family = xPreferredHostType; - - if( xDNSAsynchronous != 0 ) - { - #if ( ipconfigDNS_USE_CALLBACKS != 0 ) - { - FreeRTOS_getaddrinfo_a( pcServerName, /* The name of the node or device */ - NULL, /* Ignored for now. */ - &( xHints ), /* If not NULL: preferences. */ - &( pxResults ), /* An allocated struct, containing the results. */ - vDNS_callback, - ( void * ) NULL, /* An object or a reference. */ - pdMS_TO_TICKS( 2500U ) ); - } - #else - { - FreeRTOS_printf( ( "ipconfigDNS_USE_CALLBACKS is not defined\n" ) ); - } - #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ - } - else - { - FreeRTOS_getaddrinfo( pcServerName, /* The name of the node or device */ - NULL, /* Ignored for now. */ - &( xHints ), /* If not NULL: preferences. */ - &( pxResults ) ); /* An allocated struct, containing the results. */ - - if( pxResults != NULL ) - { - vDNS_callback( pcServerName, NULL, pxResults ); - } - } - #else /* if ( ipconfigMULTI_INTERFACE != 0 ) */ - #if ( ipconfigDNS_USE_CALLBACKS != 0 ) - FreeRTOS_gethostbyname_a( pcServerName, vDNS_callback, ( void * ) NULL, 1200U ); - #else - uint32_t ulIPAddress = FreeRTOS_gethostbyname( pcServerName ); - - if( ulIPAddress != 0U ) - { - vDNS_callback( pcServerName, NULL, ulIPAddress ); - } - #endif - #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ - } - else - { - xStatus = EStatusAsking; - } - - break; - - case EStatusAsking: - prvNTPPacketInit(); - uxSendTime = xTaskGetTickCount(); - #if ( ipconfigUSE_IPv6 != 0 ) - if( memcmp( xIPAddressFound.sin_addr6.ucBytes, in6addr_any.ucBytes, ipSIZE_OF_IPv6_ADDRESS ) != 0 ) - { - FreeRTOS_printf( ( "Sending UDP message to %pip:%u\n", - xIPAddressFound.sin_addr6.ucBytes, - FreeRTOS_ntohs( xIPAddressFound.sin_port ) ) ); - - FreeRTOS_sendto( xNTP_UDPSocket, - ( void * ) &xNTPPacket, sizeof( xNTPPacket ), - 0, - ( const struct freertos_sockaddr * ) &( xIPAddressFound ), - sizeof( xIPAddressFound ) ); - } - else - #endif /* ( ipconfigUSE_IPv6 != 0 ) */ - { - xAddress.sin_addr = ulIPAddressFound; - xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); - - FreeRTOS_printf( ( "Sending UDP message to %xip:%u\n", - ( unsigned ) FreeRTOS_ntohl( xAddress.sin_addr ), - ( unsigned ) FreeRTOS_ntohs( xAddress.sin_port ) ) ); - - FreeRTOS_sendto( xNTP_UDPSocket, - ( void * ) &xNTPPacket, - sizeof( xNTPPacket ), - 0, &( xAddress ), - sizeof( xAddress ) ); - } - - break; - - case EStatusPause: - break; - - case EStatusFailed: - break; - } - - #if ( ipconfigUSE_CALLBACKS != 0 ) - { - xSemaphoreTake( xNTPWakeupSem, 5000 ); - } - #else - { - uint32_t xAddressSize; - BaseType_t xReturned; - - xAddressSize = sizeof( xAddress ); - xReturned = FreeRTOS_recvfrom( xNTP_UDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize ); - - switch( xReturned ) - { - case 0: - case -pdFREERTOS_ERRNO_EAGAIN: - case -pdFREERTOS_ERRNO_EINTR: - break; - - default: - - if( xReturned < sizeof( xNTPPacket ) ) - { - FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) ); - } - else - { - prvReadTime( ( struct SNtpPacket * ) cRecvBuffer ); - - if( xStatus != EStatusPause ) - { - xStatus = EStatusPause; - } - } - - break; - } - } - #endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */ - } -} -/*-----------------------------------------------------------*/