1 /* 2 * FreeRTOS+TCP <DEVELOPMENT BRANCH> 3 * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * http://aws.amazon.com/freertos 25 * http://www.FreeRTOS.org 26 */ 27 28 /** 29 * @file FreeRTOS_DNS_Cache.c 30 * @brief File that handles the DNS caching option 31 */ 32 33 /* FreeRTOS+TCP includes. */ 34 #include "FreeRTOS_IP.h" 35 #include "FreeRTOS_Sockets.h" 36 #include "FreeRTOS_UDP_IP.h" 37 #include "FreeRTOS_DHCP.h" 38 #include "NetworkBufferManagement.h" 39 #include "NetworkInterface.h" 40 41 #include "FreeRTOS_DNS_Cache.h" 42 #include "FreeRTOS_DNS_Globals.h" 43 44 /* Standard includes. */ 45 #include <stdint.h> 46 #include <stdio.h> 47 #include <string.h> 48 49 #if ( ( ipconfigUSE_DNS != 0 ) && ( ipconfigUSE_DNS_CACHE == 1 ) ) 50 51 /*! 52 * @brief DNS cache structure instantiation 53 */ 54 static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ]; 55 56 /*! 57 * @brief indicates the index of a free entry in the cache structure 58 * \a DNSCacheRow_t 59 */ 60 static UBaseType_t uxFreeEntry = 0U; 61 62 /** returns the index of the hostname entry in the dns cache. */ 63 static BaseType_t prvFindEntryIndex( const char * pcName, 64 const IPv46_Address_t * pxIP, 65 UBaseType_t * uxResult ); 66 67 /** get entry at \p index from the cache. */ 68 static BaseType_t prvGetCacheIPEntry( UBaseType_t uxIndex, 69 IPv46_Address_t * pxIP, 70 uint32_t ulCurrentTimeSeconds, 71 struct freertos_addrinfo ** ppxAddressInfo ); 72 73 /** update entry at \p index in the cache. */ 74 static void prvUpdateCacheEntry( UBaseType_t uxIndex, 75 uint32_t ulTTL, 76 const IPv46_Address_t * pxIP, 77 uint32_t ulCurrentTimeSeconds ); 78 79 /** insert entry in the cache. */ 80 static void prvInsertCacheEntry( const char * pcName, 81 uint32_t ulTTL, 82 const IPv46_Address_t * pxIP, 83 uint32_t ulCurrentTimeSeconds ); 84 85 /** Copy DNS cache entries at xIndex to a linked struct addrinfo. */ 86 static void prvReadDNSCache( BaseType_t uxIndex, 87 struct freertos_addrinfo ** ppxAddressInfo ); 88 89 /*-----------------------------------------------------------*/ 90 91 #if ( ipconfigUSE_IPv4 != 0 ) 92 93 /** 94 * @brief perform a dns lookup in the local cache 95 * @param pcHostName the lookup name 96 * @return ulIPAddress with the value from the cache else returns a zero if the 97 * cache is not enabled or the lookup is not successful 98 * @post the global structure \a xDNSCache might be modified 99 */ FreeRTOS_dnslookup(const char * pcHostName)100 uint32_t FreeRTOS_dnslookup( const char * pcHostName ) 101 { 102 IPv46_Address_t xIPv46_Address; 103 104 /* Looking up an IPv4 address in the DNS cache. */ 105 ( void ) memset( &xIPv46_Address, 0, sizeof( xIPv46_Address ) ); 106 ( void ) FreeRTOS_ProcessDNSCache( pcHostName, 107 &( xIPv46_Address ), 108 0, 109 pdTRUE, 110 NULL ); 111 112 return xIPv46_Address.xIPAddress.ulIP_IPv4; 113 } 114 /*-----------------------------------------------------------*/ 115 #endif /* if ( ipconfigUSE_IPv4 != 0 ) */ 116 117 #if ( ipconfigUSE_IPv6 != 0 ) 118 119 /** 120 * @brief Perform a dns lookup in the local cache (IPv6) 121 * @param pcHostName The lookup name 122 * @param pxAddress_IPv6 The IPv6 address looked up from the cache if the return value is non zero. 123 * @return ulReturn Non zero if name is found in cache else returns a zero if the 124 * cache is not enabled or the lookup is not successful 125 * @post the global structure \a xDNSCache might be modified 126 */ FreeRTOS_dnslookup6(const char * pcHostName,IPv6_Address_t * pxAddress_IPv6)127 uint32_t FreeRTOS_dnslookup6( const char * pcHostName, 128 IPv6_Address_t * pxAddress_IPv6 ) 129 { 130 IPv46_Address_t xIPv46_Address; 131 BaseType_t xResult; 132 uint32_t ulReturn = 0U; 133 134 /* Looking up an IPv6 address in the DNS cache. */ 135 ( void ) memset( &xIPv46_Address, 0, sizeof( xIPv46_Address ) ); 136 /* Let FreeRTOS_ProcessDNSCache only return IPv6 addresses. */ 137 xIPv46_Address.xIs_IPv6 = pdTRUE; 138 xResult = FreeRTOS_ProcessDNSCache( pcHostName, &xIPv46_Address, 0, pdTRUE, NULL ); 139 140 if( xResult != pdFALSE ) 141 { 142 ( void ) memcpy( pxAddress_IPv6->ucBytes, xIPv46_Address.xIPAddress.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); 143 ulReturn = 1U; 144 } 145 146 return ulReturn; 147 } 148 /*-----------------------------------------------------------*/ 149 #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ 150 151 /** 152 * @brief perform a dns update in the local cache 153 * @param pcName the lookup name 154 * @param pxIP the ip value to insert/replace (IPv4/v6) 155 * @param ulTTL Time To live (in seconds) 156 * @param xLookUp Ignored 157 * @param ppxAddressInfo A pointer to a pointer where the find results 158 * will be stored. 159 * @return this is a dummy return, we are actually ignoring the return value 160 * from this function 161 * @post the global structure \a xDNSCache might be modified 162 */ FreeRTOS_dns_update(const char * pcName,IPv46_Address_t * pxIP,uint32_t ulTTL,BaseType_t xLookUp,struct freertos_addrinfo ** ppxAddressInfo)163 BaseType_t FreeRTOS_dns_update( const char * pcName, 164 IPv46_Address_t * pxIP, 165 uint32_t ulTTL, 166 BaseType_t xLookUp, 167 struct freertos_addrinfo ** ppxAddressInfo ) 168 { 169 /* _HT_ we can as well remove the parameter 'xLookUp'. */ 170 ( void ) xLookUp; 171 ( void ) FreeRTOS_ProcessDNSCache( pcName, 172 pxIP, 173 ulTTL, 174 pdFALSE, 175 ppxAddressInfo ); 176 return pdTRUE; 177 } 178 179 /** 180 * @brief perform a dns clear in the local cache 181 * @post the global structure \a xDNSCache is modified 182 */ FreeRTOS_dnsclear(void)183 void FreeRTOS_dnsclear( void ) 184 { 185 ( void ) memset( xDNSCache, 0x0, sizeof( xDNSCache ) ); 186 uxFreeEntry = 0U; 187 } 188 189 /** 190 * @brief process a DNS Cache request (get, update, or insert) 191 * 192 * @param[in] pcName the name of the host 193 * @param[in,out] pxIP when doing a lookup, will be set, when doing an update, 194 * will be read. 195 * @param[in] ulTTL Time To Live (in seconds) 196 * @param[in] xLookUp pdTRUE if a look-up is expected, pdFALSE, when the DNS cache must 197 * be updated. 198 * @param[in,out] ppxAddressInfo A pointer to a pointer where the find results 199 * will be stored. 200 * @return whether the operation was successful 201 * @post the global structure \a xDNSCache might be modified 202 */ FreeRTOS_ProcessDNSCache(const char * pcName,IPv46_Address_t * pxIP,uint32_t ulTTL,BaseType_t xLookUp,struct freertos_addrinfo ** ppxAddressInfo)203 BaseType_t FreeRTOS_ProcessDNSCache( const char * pcName, 204 IPv46_Address_t * pxIP, 205 uint32_t ulTTL, 206 BaseType_t xLookUp, 207 struct freertos_addrinfo ** ppxAddressInfo ) 208 { 209 UBaseType_t uxIndex; 210 BaseType_t xResult; 211 /* Get the current time in clock-ticks. */ 212 TickType_t xCurrentTickCount = xTaskGetTickCount(); 213 /* In milliseconds. */ 214 uint32_t ulCurrentTimeSeconds; 215 216 configASSERT( ( pcName != NULL ) ); 217 218 if( xLookUp != pdFALSE ) 219 { 220 pxIP->xIPAddress.ulIP_IPv4 = 0U; 221 } 222 223 ulCurrentTimeSeconds = ( uint32_t ) ( ( xCurrentTickCount / portTICK_PERIOD_MS ) / 1000U ); 224 xResult = prvFindEntryIndex( pcName, pxIP, &uxIndex ); 225 226 if( xResult == pdTRUE ) 227 { /* Element found */ 228 /* Is this function called for a lookup or to add/update an IP address? */ 229 if( xLookUp == pdTRUE ) 230 { 231 /* This statement can only be reached when xResult is true; which 232 * implies that the entry is present and a 'get' operation will result 233 * in success. Therefore, it is safe to ignore the return value of the 234 * below function. */ 235 ( void ) prvGetCacheIPEntry( uxIndex, 236 pxIP, 237 ulCurrentTimeSeconds, 238 ppxAddressInfo ); 239 } 240 else 241 { 242 prvUpdateCacheEntry( uxIndex, 243 ulTTL, 244 pxIP, 245 ulCurrentTimeSeconds ); 246 } 247 } 248 else /* Element not Found xResult = pdFALSE */ 249 { 250 if( xLookUp == pdTRUE ) 251 { 252 pxIP->xIPAddress.ulIP_IPv4 = 0U; 253 } 254 else 255 { 256 prvInsertCacheEntry( pcName, 257 ulTTL, 258 pxIP, 259 ulCurrentTimeSeconds ); 260 } 261 } 262 263 #if ( ipconfigHAS_DEBUG_PRINTF != 0 ) 264 if( ( xLookUp == pdFALSE ) || ( pxIP->xIPAddress.ulIP_IPv4 != 0U ) ) 265 { 266 char pcAddress[ 40 ]; 267 IP_Address_t xAddress; 268 BaseType_t xFamily = FREERTOS_AF_INET; 269 270 switch( pxIP->xIs_IPv6 ) 271 { 272 #if ( ipconfigUSE_IPv6 != 0 ) 273 case pdTRUE: 274 ( void ) memcpy( xAddress.xIP_IPv6.ucBytes, pxIP->xIPAddress.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); 275 xFamily = FREERTOS_AF_INET6; 276 break; 277 #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ 278 279 #if ( ipconfigUSE_IPv4 != 0 ) 280 case pdFALSE: 281 xAddress.ulIP_IPv4 = pxIP->xIPAddress.ulIP_IPv4; 282 break; 283 #endif /* if ( ipconfigUSE_IPv4 != 0 ) */ 284 285 default: 286 /* MISRA 16.4 Compliance */ 287 FreeRTOS_debug_printf( ( "FreeRTOS_ProcessDNSCache: Undefined IP Type \n" ) ); 288 break; 289 } 290 291 ( void ) FreeRTOS_inet_ntop( xFamily, 292 ( const void * ) xAddress.xIP_IPv6.ucBytes, 293 pcAddress, 294 ( socklen_t ) sizeof( pcAddress ) ); 295 FreeRTOS_debug_printf( ( "FreeRTOS_ProcessDNSCache: %s: '%s' @ %s (TTL %u)\n", 296 ( xLookUp != 0 ) ? "look-up" : "add", 297 pcName, 298 pcAddress, 299 ( unsigned ) FreeRTOS_ntohl( ulTTL ) ) ); 300 } 301 #endif /* ( ipconfigHAS_DEBUG_PRINTF != 0 ) */ 302 303 return xResult; 304 } 305 306 /** 307 * @brief returns the index of the hostname entry in the dns cache. 308 * @param[in] pcName find it in the cache 309 * @param[in] pxIP ip address 310 * @param [out] uxResult index number 311 * @returns res pdTRUE if index in found else pdFALSE 312 */ prvFindEntryIndex(const char * pcName,const IPv46_Address_t * pxIP,UBaseType_t * uxResult)313 static BaseType_t prvFindEntryIndex( const char * pcName, 314 const IPv46_Address_t * pxIP, 315 UBaseType_t * uxResult ) 316 { 317 BaseType_t xReturn = pdFALSE; 318 UBaseType_t uxIndex; 319 320 /* For each entry in the DNS cache table. */ 321 for( uxIndex = 0; uxIndex < ipconfigDNS_CACHE_ENTRIES; uxIndex++ ) 322 { 323 if( xDNSCache[ uxIndex ].pcName[ 0 ] == ( char ) 0 ) 324 { /* empty slot */ 325 continue; 326 } 327 328 if( strcmp( xDNSCache[ uxIndex ].pcName, pcName ) == 0 ) 329 { /* hostname found */ 330 /* IPv6 is enabled, See if the cache entry has the correct type. */ 331 if( pxIP->xIs_IPv6 == xDNSCache[ uxIndex ].xAddresses[ 0 ].xIs_IPv6 ) 332 { 333 xReturn = pdTRUE; 334 *uxResult = uxIndex; 335 break; 336 } 337 } 338 } 339 340 return xReturn; 341 } 342 /*-----------------------------------------------------------*/ 343 344 /** 345 * @brief get entry at \p index from the cache 346 * @param[in] uxIndex index in the cache 347 * @param[out] pxIP fill it with the result 348 * @param[in] ulCurrentTimeSeconds current time 349 * @param[out] ppxAddressInfo Target to store the DNS entries. 350 * @returns \c pdTRUE if the value is valid \c pdFALSE otherwise 351 * @post the global structure \a xDNSCache might be modified 352 * 353 */ 354 prvGetCacheIPEntry(UBaseType_t uxIndex,IPv46_Address_t * pxIP,uint32_t ulCurrentTimeSeconds,struct freertos_addrinfo ** ppxAddressInfo)355 static BaseType_t prvGetCacheIPEntry( UBaseType_t uxIndex, 356 IPv46_Address_t * pxIP, 357 uint32_t ulCurrentTimeSeconds, 358 struct freertos_addrinfo ** ppxAddressInfo ) 359 { 360 BaseType_t isRead; 361 uint32_t ulIPAddressIndex = 0; 362 uint32_t ulAge = ulCurrentTimeSeconds - xDNSCache[ uxIndex ].ulTimeWhenAddedInSeconds; 363 364 /* Confirm that the record is still fresh. 365 * The field ulTTL was stored as network-endian. */ 366 if( ulAge < FreeRTOS_ntohl( xDNSCache[ uxIndex ].ulTTL ) ) 367 { 368 #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) 369 uint8_t ucIndex; 370 371 /* The ucCurrentIPAddress value increments without bound and will rollover, */ 372 /* modulo it by the number of IP addresses to keep it in range. */ 373 /* Also perform a final modulo by the max number of IP addresses */ 374 /* per DNS cache entry to prevent out-of-bounds access in the event */ 375 /* that ucNumIPAddresses has been corrupted. */ 376 377 ucIndex = xDNSCache[ uxIndex ].ucCurrentIPAddress % xDNSCache[ uxIndex ].ucNumIPAddresses; 378 ucIndex = ucIndex % ( uint8_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY; 379 ulIPAddressIndex = ucIndex; 380 381 xDNSCache[ uxIndex ].ucCurrentIPAddress++; 382 #endif /* if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) */ 383 384 ( void ) memcpy( pxIP, &( xDNSCache[ uxIndex ].xAddresses[ ulIPAddressIndex ] ), sizeof( *pxIP ) ); 385 isRead = pdTRUE; 386 387 if( ppxAddressInfo != NULL ) 388 { 389 /* Copy all entries from position 'uxIndex' to a linked struct addrinfo. */ 390 prvReadDNSCache( ( BaseType_t ) uxIndex, ppxAddressInfo ); 391 } 392 } 393 else 394 { 395 /* Age out the old cached record. */ 396 xDNSCache[ uxIndex ].pcName[ 0 ] = ( char ) 0; 397 isRead = pdFALSE; 398 } 399 400 return isRead; 401 } 402 /*-----------------------------------------------------------*/ 403 404 /** 405 * @brief update entry at \p index in the cache 406 * @param[in] uxIndex index in the cache 407 * @param[in] ulTTL time to live (in seconds) 408 * @param[in] pxIP ip to update the cache with 409 * @param[in] ulCurrentTimeSeconds current time 410 * @post the global structure \a xDNSCache is modified 411 */ prvUpdateCacheEntry(UBaseType_t uxIndex,uint32_t ulTTL,const IPv46_Address_t * pxIP,uint32_t ulCurrentTimeSeconds)412 static void prvUpdateCacheEntry( UBaseType_t uxIndex, 413 uint32_t ulTTL, 414 const IPv46_Address_t * pxIP, 415 uint32_t ulCurrentTimeSeconds ) 416 { 417 uint32_t ulIPAddressIndex = 0; 418 419 #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) 420 if( xDNSCache[ uxIndex ].ucNumIPAddresses < 421 ( uint8_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ) 422 { 423 /* If more answers exist than there are IP address storage 424 * slots they will overwrite entry 0 */ 425 ulIPAddressIndex = xDNSCache[ uxIndex ].ucNumIPAddresses; 426 xDNSCache[ uxIndex ].ucNumIPAddresses++; 427 } 428 #endif 429 ( void ) memcpy( &( xDNSCache[ uxIndex ].xAddresses[ ulIPAddressIndex ] ), pxIP, sizeof( *pxIP ) ); 430 xDNSCache[ uxIndex ].ulTTL = ulTTL; 431 xDNSCache[ uxIndex ].ulTimeWhenAddedInSeconds = ulCurrentTimeSeconds; 432 } 433 /*-----------------------------------------------------------*/ 434 435 /** 436 * @brief insert entry in the cache 437 * @param[in] pcName cache entry key 438 * @param[in] ulTTL time to live (in seconds) 439 * @param[in] pxIP ip address 440 * @param[in] ulCurrentTimeSeconds current time 441 * @post the global structure \a xDNSCache is modified 442 */ prvInsertCacheEntry(const char * pcName,uint32_t ulTTL,const IPv46_Address_t * pxIP,uint32_t ulCurrentTimeSeconds)443 static void prvInsertCacheEntry( const char * pcName, 444 uint32_t ulTTL, 445 const IPv46_Address_t * pxIP, 446 uint32_t ulCurrentTimeSeconds ) 447 { 448 /* Add or update the item. */ 449 if( strlen( pcName ) < ( size_t ) ipconfigDNS_CACHE_NAME_LENGTH ) 450 { 451 ( void ) strcpy( xDNSCache[ uxFreeEntry ].pcName, pcName ); 452 ( void ) memcpy( &( xDNSCache[ uxFreeEntry ].xAddresses[ 0 ] ), pxIP, sizeof( *pxIP ) ); 453 454 455 xDNSCache[ uxFreeEntry ].ulTTL = ulTTL; 456 xDNSCache[ uxFreeEntry ].ulTimeWhenAddedInSeconds = ulCurrentTimeSeconds; 457 #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) 458 xDNSCache[ uxFreeEntry ].ucNumIPAddresses = 1; 459 xDNSCache[ uxFreeEntry ].ucCurrentIPAddress = 0; 460 461 /* Initialize all remaining IP addresses in this entry to 0 */ 462 ( void ) memset( &xDNSCache[ uxFreeEntry ].xAddresses[ 1 ], 463 0, 464 sizeof( xDNSCache[ uxFreeEntry ].xAddresses[ 1 ] ) * 465 ( ( uint32_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY - 1U ) ); 466 #endif 467 uxFreeEntry++; 468 469 if( uxFreeEntry == ipconfigDNS_CACHE_ENTRIES ) 470 { 471 uxFreeEntry = 0; 472 } 473 } 474 } 475 /*-----------------------------------------------------------*/ 476 477 /** 478 * @brief Copy DNS cache entries at uxIndex to a linked struct addrinfo. 479 * @param[in] uxIndex The index from where entries must be copied. 480 * @param[out] ppxAddressInfo Target to store the DNS entries. 481 */ prvReadDNSCache(BaseType_t uxIndex,struct freertos_addrinfo ** ppxAddressInfo)482 static void prvReadDNSCache( BaseType_t uxIndex, 483 struct freertos_addrinfo ** ppxAddressInfo ) 484 { 485 size_t uxIPAddressIndex; 486 size_t uxNumIPAddresses = 1U; 487 const IPv46_Address_t * pxAddresses; 488 struct freertos_addrinfo * pxNewAddress = NULL; 489 struct freertos_addrinfo ** ppxLastAddress = ppxAddressInfo; 490 491 #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) 492 uxNumIPAddresses = ( size_t ) xDNSCache[ uxIndex ].ucNumIPAddresses; 493 494 if( uxNumIPAddresses > ( size_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ) 495 { 496 /* Make this a configASSERT()? */ 497 uxNumIPAddresses = ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY; 498 } 499 #endif /* ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) */ 500 501 for( uxIPAddressIndex = 0; uxIPAddressIndex < uxNumIPAddresses; uxIPAddressIndex++ ) 502 { 503 pxAddresses = &( xDNSCache[ uxIndex ].xAddresses[ uxIPAddressIndex ] ); 504 505 switch( pxAddresses->xIs_IPv6 ) /* LCOV_EXCL_BR_LINE - xIs_IPv6 is always either pdFALSE or pdTRUE. */ 506 { 507 #if ( ipconfigUSE_IPv4 != 0 ) 508 case pdFALSE: 509 { 510 const uint8_t * ucBytes = ( const uint8_t * ) &( pxAddresses->xIPAddress.ulIP_IPv4 ); 511 pxNewAddress = pxNew_AddrInfo( xDNSCache[ uxIndex ].pcName, FREERTOS_AF_INET4, ucBytes ); 512 } 513 break; 514 #endif /* ( ipconfigUSE_IPv4 != 0 ) */ 515 516 #if ( ipconfigUSE_IPv6 != 0 ) 517 case pdTRUE: 518 pxNewAddress = pxNew_AddrInfo( xDNSCache[ uxIndex ].pcName, FREERTOS_AF_INET6, pxAddresses->xIPAddress.xIP_IPv6.ucBytes ); 519 break; 520 #endif /* ( ipconfigUSE_IPv6 != 0 ) */ 521 522 default: /* LCOV_EXCL_LINE - xIs_IPv6 is always either pdFALSE or FREERTOS_AF_INET6. */ 523 /* MISRA 16.4 Compliance */ 524 FreeRTOS_debug_printf( ( "prvReadDNSCache: Undefined IP Type \n" ) ); 525 break; /* LCOV_EXCL_LINE - xIs_IPv6 is always either pdFALSE or FREERTOS_AF_INET6. */ 526 } 527 528 if( pxNewAddress == NULL ) 529 { 530 /* Malloc must has failed. */ 531 break; 532 } 533 534 /* Set either 'ppxAddressInfo' or 'pxNewAddress->ai_next'. */ 535 *( ppxLastAddress ) = pxNewAddress; 536 537 ppxLastAddress = &( pxNewAddress->ai_next ); 538 } 539 } 540 /*-----------------------------------------------------------*/ 541 542 /** 543 * @brief Lookup the given hostname in the DNS cache 544 * @param[in] pcHostName THe host name to lookup 545 * @param[in] xFamily IP type FREERTOS_AF_INET6 / FREERTOS_AF_INET4 546 * @param[out] ppxAddressInfo Target to store the DNS entries. 547 * @returns This function returns either a valid IPv4 address, or 548 * in case of an IPv6 lookup, it will return a non-zero. 549 */ Prepare_CacheLookup(const char * pcHostName,BaseType_t xFamily,struct freertos_addrinfo ** ppxAddressInfo)550 uint32_t Prepare_CacheLookup( const char * pcHostName, 551 BaseType_t xFamily, 552 struct freertos_addrinfo ** ppxAddressInfo ) 553 { 554 uint32_t ulIPAddress = 0U; 555 IPv46_Address_t xIPv46_Address; 556 557 switch( xFamily ) 558 { 559 #if ( ipconfigUSE_IPv4 != 0 ) 560 case FREERTOS_AF_INET: 561 { 562 BaseType_t xFound; 563 564 xIPv46_Address.xIs_IPv6 = pdFALSE; 565 xFound = FreeRTOS_ProcessDNSCache( pcHostName, &( xIPv46_Address ), 0, pdTRUE, ppxAddressInfo ); 566 567 if( xFound != 0 ) 568 { 569 if( ( ppxAddressInfo != NULL ) && ( *( ppxAddressInfo ) != NULL ) ) 570 { 571 const struct freertos_sockaddr * sockaddr = ( *( ppxAddressInfo ) )->ai_addr; 572 573 ulIPAddress = sockaddr->sin_address.ulIP_IPv4; 574 } 575 } 576 else 577 { 578 /* prvGetHostByName will be called to start a DNS lookup. */ 579 } 580 } 581 break; 582 #endif /* ( ipconfigUSE_IPv4 != 0 ) */ 583 584 #if ( ipconfigUSE_IPv6 != 0 ) 585 case FREERTOS_AF_INET6: 586 { 587 BaseType_t xFound; 588 589 xIPv46_Address.xIs_IPv6 = pdTRUE; 590 xFound = FreeRTOS_ProcessDNSCache( pcHostName, &( xIPv46_Address ), 0, pdTRUE, ppxAddressInfo ); 591 592 if( xFound != 0 ) 593 { 594 if( ( ppxAddressInfo != NULL ) && ( *( ppxAddressInfo ) != NULL ) ) 595 { 596 /* This function returns either a valid IPv4 address, or 597 * in case of an IPv6 lookup, it will return a non-zero */ 598 ulIPAddress = 1U; 599 } 600 } 601 else 602 { 603 /* prvGetHostByName will be called to start a DNS lookup. */ 604 } 605 } 606 break; 607 #endif /* ( ipconfigUSE_IPv6 != 0 ) */ 608 609 default: 610 /* MISRA 16.4 Compliance */ 611 FreeRTOS_debug_printf( ( "Prepare_CacheLookup: Undefined xFamily \n" ) ); 612 break; 613 } 614 615 return ulIPAddress; 616 } 617 /*-----------------------------------------------------------*/ 618 619 #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) 620 621 /** 622 * @brief For debugging only: prints the contents of the DNS cache table. 623 */ vShowDNSCacheTable(void)624 void vShowDNSCacheTable( void ) 625 { 626 UBaseType_t xEntry; 627 UBaseType_t xSubEntry; 628 629 for( xEntry = 0; xEntry < ipconfigDNS_CACHE_ENTRIES; xEntry++ ) 630 { 631 const DNSCacheRow_t * pxRow = &( xDNSCache[ xEntry ] ); 632 633 if( pxRow->pcName[ 0 ] != ( char ) 0 ) 634 { 635 FreeRTOS_printf( ( "Entry %2u: %s use %u/%u\n", 636 ( unsigned ) xEntry, 637 pxRow->pcName, 638 ( unsigned ) pxRow->ucCurrentIPAddress, 639 ( unsigned ) pxRow->ucNumIPAddresses ) ); 640 641 for( xSubEntry = 0; xSubEntry < pxRow->ucNumIPAddresses; xSubEntry++ ) 642 { 643 char pcAddress[ 40 ] = ""; 644 645 switch( pxRow->xAddresses[ 0 ].xIs_IPv6 ) 646 { 647 /* The first entry determines the type of row: 648 * either IPv4 or IPv6. */ 649 #if ( ipconfigUSE_IPv4 != 0 ) 650 case pdFALSE: 651 ( void ) FreeRTOS_inet_ntop( FREERTOS_AF_INET4, 652 ( const void * ) &( pxRow->xAddresses[ xSubEntry ].xIPAddress.ulIP_IPv4 ), 653 pcAddress, 654 sizeof( pcAddress ) ); 655 break; 656 #endif /* ( ipconfigUSE_IPv4 != 0 ) */ 657 658 #if ( ipconfigUSE_IPv6 != 0 ) 659 case pdTRUE: 660 ( void ) FreeRTOS_inet_ntop( FREERTOS_AF_INET6, 661 ( const void * ) pxRow->xAddresses[ xSubEntry ].xIPAddress.xIP_IPv6.ucBytes, 662 pcAddress, 663 sizeof( pcAddress ) ); 664 break; 665 #endif /* ( ipconfigUSE_IPv6 != 0 ) */ 666 667 default: 668 /* MISRA 16.4 Compliance */ 669 FreeRTOS_debug_printf( ( "vShowDNSCacheTable: Undefined IP Type \n" ) ); 670 break; 671 } 672 673 FreeRTOS_printf( ( " %2u: %s\n", 674 ( unsigned ) xSubEntry, 675 pcAddress ) ); 676 } 677 } 678 } 679 } 680 #endif /* if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) */ 681 /*-----------------------------------------------------------*/ 682 683 #endif /* if ( ( ipconfigUSE_DNS != 0 ) && ( ipconfigUSE_DNS_CACHE == 1 ) ) */ 684