Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dns_cache.c Source File

dns_cache.c

Go to the documentation of this file.
00001 /**
00002  * @file dns_cache.c
00003  * @brief DNS cache management
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL DNS_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <stdlib.h>
00034 #include "core/net.h"
00035 #include "dns/dns_cache.h"
00036 #include "dns/dns_client.h"
00037 #include "mdns/mdns_client.h"
00038 #include "netbios/nbns_client.h"
00039 #include "core/udp.h"
00040 #include "debug.h"
00041 
00042 //Check TCP/IP stack configuration
00043 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
00044    NBNS_CLIENT_SUPPORT == ENABLED)
00045 
00046 //Tick counter to handle periodic operations
00047 systime_t dnsTickCounter;
00048 //DNS cache
00049 DnsCacheEntry dnsCache[DNS_CACHE_SIZE];
00050 
00051 
00052 /**
00053  * @brief DNS cache initialization
00054  * @return Error code
00055  **/
00056 
00057 error_t dnsInit(void)
00058 {
00059    //Initialize DNS cache
00060    memset(dnsCache, 0, sizeof(dnsCache));
00061 
00062    //Successful initialization
00063    return NO_ERROR;
00064 }
00065 
00066 
00067 /**
00068  * @brief Flush DNS cache
00069  * @param[in] interface Underlying network interface
00070  **/
00071 
00072 void dnsFlushCache(NetInterface *interface)
00073 {
00074    uint_t i;
00075    DnsCacheEntry *entry;
00076 
00077    //Go through DNS cache
00078    for(i = 0; i < DNS_CACHE_SIZE; i++)
00079    {
00080       //Point to the current entry
00081       entry = &dnsCache[i];
00082 
00083       //Check whether the entry is currently in used
00084       if(entry->state != DNS_STATE_NONE)
00085       {
00086          //Delete DNS entries only for the given network interface
00087          if(entry->interface == interface)
00088             dnsDeleteEntry(entry);
00089       }
00090    }
00091 }
00092 
00093 
00094 /**
00095  * @brief Create a new entry in the DNS cache
00096  * @return Pointer to the newly created entry
00097  **/
00098 
00099 DnsCacheEntry *dnsCreateEntry(void)
00100 {
00101    uint_t i;
00102    DnsCacheEntry *entry;
00103    DnsCacheEntry *oldestEntry;
00104 
00105    //Keep track of the oldest entry
00106    oldestEntry = &dnsCache[0];
00107 
00108    //Loop through DNS cache entries
00109    for(i = 0; i < DNS_CACHE_SIZE; i++)
00110    {
00111       //Point to the current entry
00112       entry = &dnsCache[i];
00113 
00114       //Check whether the entry is currently in used or not
00115       if(entry->state == DNS_STATE_NONE)
00116       {
00117          //Erase contents
00118          memset(entry, 0, sizeof(DnsCacheEntry));
00119          //Return a pointer to the DNS entry
00120          return entry;
00121       }
00122 
00123       //Keep track of the oldest entry in the table
00124       if(timeCompare(entry->timestamp, oldestEntry->timestamp) < 0)
00125          oldestEntry = entry;
00126    }
00127 
00128    //The oldest entry is removed whenever the table runs out of space
00129    dnsDeleteEntry(oldestEntry);
00130    //Erase contents
00131    memset(oldestEntry, 0, sizeof(DnsCacheEntry));
00132    //Return a pointer to the DNS entry
00133    return oldestEntry;
00134 }
00135 
00136 
00137 /**
00138  * @brief Delete the specified DNS cache entry
00139  * @param[in] entry Pointer to the DNS cache entry to be deleted
00140  **/
00141 
00142 void dnsDeleteEntry(DnsCacheEntry *entry)
00143 {
00144    //Make sure the specified entry is valid
00145    if(entry != NULL)
00146    {
00147 #if (DNS_CLIENT_SUPPORT == ENABLED)
00148       //DNS resolver?
00149       if(entry->protocol == HOST_NAME_RESOLVER_DNS)
00150       {
00151          //Name resolution in progress?
00152          if(entry->state == DNS_STATE_IN_PROGRESS)
00153          {
00154             //Unregister user callback
00155             udpDetachRxCallback(entry->interface, entry->port);
00156          }
00157       }
00158 #endif
00159       //Delete DNS cache entry
00160       entry->state = DNS_STATE_NONE;
00161    }
00162 }
00163 
00164 
00165 /**
00166  * @brief Search the DNS cache for a given domain name
00167  * @param[in] interface Underlying network interface
00168  * @param[in] name Domain name
00169  * @param[in] type Host type (IPv4 or IPv6)
00170  * @param[in] protocol Host name resolution protocol
00171  * @return A pointer to the matching DNS entry is returned. NULL is returned
00172  *   if the specified domain name could not be found in the DNS cache
00173  **/
00174 
00175 DnsCacheEntry *dnsFindEntry(NetInterface *interface,
00176    const char_t *name, HostType type, HostnameResolver protocol)
00177 {
00178    uint_t i;
00179    DnsCacheEntry *entry;
00180 
00181    //Loop through DNS cache entries
00182    for(i = 0; i < DNS_CACHE_SIZE; i++)
00183    {
00184       //Point to the current entry
00185       entry = &dnsCache[i];
00186 
00187       //Make sure that the entry is currently in used
00188       if(entry->state == DNS_STATE_NONE)
00189          continue;
00190 
00191       //Filter out entries that do not match the specified criteria
00192       if(entry->interface != interface)
00193          continue;
00194       if(entry->type != type && type != HOST_TYPE_ANY)
00195          continue;
00196       if(entry->protocol != protocol && protocol != HOST_NAME_RESOLVER_ANY)
00197          continue;
00198 
00199       //Does the entry match the specified domain name?
00200       if(name == NULL || !strcasecmp(entry->name, name))
00201          return entry;
00202    }
00203 
00204    //No matching entry in the DNS cache...
00205    return NULL;
00206 }
00207 
00208 
00209 /**
00210  * @brief DNS timer handler
00211  *
00212  * This routine must be periodically called by the TCP/IP stack to
00213  * manage DNS cache
00214  *
00215  **/
00216 
00217 void dnsTick(void)
00218 {
00219    error_t error;
00220    uint_t i;
00221    systime_t time;
00222    DnsCacheEntry *entry;
00223 
00224    //Get current time
00225    time = osGetSystemTime();
00226 
00227    //Go through DNS cache
00228    for(i = 0; i < DNS_CACHE_SIZE; i++)
00229    {
00230       //Point to the current entry
00231       entry = &dnsCache[i];
00232 
00233       //Name resolution in progress?
00234       if(entry->state == DNS_STATE_IN_PROGRESS)
00235       {
00236          //The request timed out?
00237          if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
00238          {
00239             //Check whether the maximum number of retransmissions has been exceeded
00240             if(entry->retransmitCount > 0)
00241             {
00242 #if (DNS_CLIENT_SUPPORT == ENABLED)
00243                //DNS resolver?
00244                if(entry->protocol == HOST_NAME_RESOLVER_DNS)
00245                {
00246                   //Retransmit DNS query
00247                   error = dnsSendQuery(entry);
00248                }
00249                else
00250 #endif
00251 #if (MDNS_CLIENT_SUPPORT == ENABLED)
00252                //mDNS resolver?
00253                if(entry->protocol == HOST_NAME_RESOLVER_MDNS)
00254                {
00255                   //Retransmit mDNS query
00256                   error = mdnsClientSendQuery(entry);
00257                }
00258                else
00259 #endif
00260 #if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
00261                //NetBIOS Name Service resolver?
00262                if(entry->protocol == HOST_NAME_RESOLVER_NBNS)
00263                {
00264                   //Retransmit NBNS query
00265                   error = nbnsSendQuery(entry);
00266                }
00267                else
00268 #endif
00269                //Unknown protocol?
00270                {
00271                   error = ERROR_FAILURE;
00272                }
00273 
00274                //Query message successfully sent?
00275                if(!error)
00276                {
00277                   //Save the time at which the query message was sent
00278                   entry->timestamp = time;
00279                   //The timeout value is doubled for each subsequent retransmission
00280                   entry->timeout = MIN(entry->timeout * 2, entry->maxTimeout);
00281                   //Decrement retransmission counter
00282                   entry->retransmitCount--;
00283                }
00284                else
00285                {
00286                   //The entry should be deleted since name resolution has failed
00287                   dnsDeleteEntry(entry);
00288                }
00289             }
00290 #if (DNS_CLIENT_SUPPORT == ENABLED)
00291             //DNS resolver?
00292             else if(entry->protocol == HOST_NAME_RESOLVER_DNS)
00293             {
00294                //Select the next DNS server
00295                entry->dnsServerNum++;
00296                //Initialize retransmission counter
00297                entry->retransmitCount = DNS_CLIENT_MAX_RETRIES;
00298                //Send DNS query
00299                error = dnsSendQuery(entry);
00300 
00301                //DNS message successfully sent?
00302                if(!error)
00303                {
00304                   //Save the time at which the query message was sent
00305                   entry->timestamp = time;
00306                   //Set timeout value
00307                   entry->timeout = DNS_CLIENT_INIT_TIMEOUT;
00308                   //Decrement retransmission counter
00309                   entry->retransmitCount--;
00310                }
00311                else
00312                {
00313                   //The entry should be deleted since name resolution has failed
00314                   dnsDeleteEntry(entry);
00315                }
00316             }
00317 #endif
00318             else
00319             {
00320                //The maximum number of retransmissions has been exceeded
00321                dnsDeleteEntry(entry);
00322             }
00323          }
00324       }
00325       //Name successfully resolved?
00326       else if(entry->state == DNS_STATE_RESOLVED)
00327       {
00328          //Check the lifetime of the current DNS cache entry
00329          if(timeCompare(time, entry->timestamp + entry->timeout) >= 0)
00330          {
00331             //Periodically time out DNS cache entries
00332             dnsDeleteEntry(entry);
00333          }
00334       }
00335    }
00336 }
00337 
00338 #endif
00339