Webserver+3d print
Diff: cyclone_tcp/dns/dns_cache.c
- Revision:
- 0:8918a71cdbe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cyclone_tcp/dns/dns_cache.c Sat Feb 04 18:15:49 2017 +0000 @@ -0,0 +1,339 @@ +/** + * @file dns_cache.c + * @brief DNS cache management + * + * @section License + * + * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneTCP Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 1.7.6 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL DNS_TRACE_LEVEL + +//Dependencies +#include <stdlib.h> +#include "core/net.h" +#include "dns/dns_cache.h" +#include "dns/dns_client.h" +#include "mdns/mdns_client.h" +#include "netbios/nbns_client.h" +#include "core/udp.h" +#include "debug.h" + +//Check TCP/IP stack configuration +#if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \ + NBNS_CLIENT_SUPPORT == ENABLED) + +//Tick counter to handle periodic operations +systime_t dnsTickCounter; +//DNS cache +DnsCacheEntry dnsCache[DNS_CACHE_SIZE]; + + +/** + * @brief DNS cache initialization + * @return Error code + **/ + +error_t dnsInit(void) +{ + //Initialize DNS cache + memset(dnsCache, 0, sizeof(dnsCache)); + + //Successful initialization + return NO_ERROR; +} + + +/** + * @brief Flush DNS cache + * @param[in] interface Underlying network interface + **/ + +void dnsFlushCache(NetInterface *interface) +{ + uint_t i; + DnsCacheEntry *entry; + + //Go through DNS cache + for(i = 0; i < DNS_CACHE_SIZE; i++) + { + //Point to the current entry + entry = &dnsCache[i]; + + //Check whether the entry is currently in used + if(entry->state != DNS_STATE_NONE) + { + //Delete DNS entries only for the given network interface + if(entry->interface == interface) + dnsDeleteEntry(entry); + } + } +} + + +/** + * @brief Create a new entry in the DNS cache + * @return Pointer to the newly created entry + **/ + +DnsCacheEntry *dnsCreateEntry(void) +{ + uint_t i; + DnsCacheEntry *entry; + DnsCacheEntry *oldestEntry; + + //Keep track of the oldest entry + oldestEntry = &dnsCache[0]; + + //Loop through DNS cache entries + for(i = 0; i < DNS_CACHE_SIZE; i++) + { + //Point to the current entry + entry = &dnsCache[i]; + + //Check whether the entry is currently in used or not + if(entry->state == DNS_STATE_NONE) + { + //Erase contents + memset(entry, 0, sizeof(DnsCacheEntry)); + //Return a pointer to the DNS entry + return entry; + } + + //Keep track of the oldest entry in the table + if(timeCompare(entry->timestamp, oldestEntry->timestamp) < 0) + oldestEntry = entry; + } + + //The oldest entry is removed whenever the table runs out of space + dnsDeleteEntry(oldestEntry); + //Erase contents + memset(oldestEntry, 0, sizeof(DnsCacheEntry)); + //Return a pointer to the DNS entry + return oldestEntry; +} + + +/** + * @brief Delete the specified DNS cache entry + * @param[in] entry Pointer to the DNS cache entry to be deleted + **/ + +void dnsDeleteEntry(DnsCacheEntry *entry) +{ + //Make sure the specified entry is valid + if(entry != NULL) + { +#if (DNS_CLIENT_SUPPORT == ENABLED) + //DNS resolver? + if(entry->protocol == HOST_NAME_RESOLVER_DNS) + { + //Name resolution in progress? + if(entry->state == DNS_STATE_IN_PROGRESS) + { + //Unregister user callback + udpDetachRxCallback(entry->interface, entry->port); + } + } +#endif + //Delete DNS cache entry + entry->state = DNS_STATE_NONE; + } +} + + +/** + * @brief Search the DNS cache for a given domain name + * @param[in] interface Underlying network interface + * @param[in] name Domain name + * @param[in] type Host type (IPv4 or IPv6) + * @param[in] protocol Host name resolution protocol + * @return A pointer to the matching DNS entry is returned. NULL is returned + * if the specified domain name could not be found in the DNS cache + **/ + +DnsCacheEntry *dnsFindEntry(NetInterface *interface, + const char_t *name, HostType type, HostnameResolver protocol) +{ + uint_t i; + DnsCacheEntry *entry; + + //Loop through DNS cache entries + for(i = 0; i < DNS_CACHE_SIZE; i++) + { + //Point to the current entry + entry = &dnsCache[i]; + + //Make sure that the entry is currently in used + if(entry->state == DNS_STATE_NONE) + continue; + + //Filter out entries that do not match the specified criteria + if(entry->interface != interface) + continue; + if(entry->type != type && type != HOST_TYPE_ANY) + continue; + if(entry->protocol != protocol && protocol != HOST_NAME_RESOLVER_ANY) + continue; + + //Does the entry match the specified domain name? + if(name == NULL || !strcasecmp(entry->name, name)) + return entry; + } + + //No matching entry in the DNS cache... + return NULL; +} + + +/** + * @brief DNS timer handler + * + * This routine must be periodically called by the TCP/IP stack to + * manage DNS cache + * + **/ + +void dnsTick(void) +{ + error_t error; + uint_t i; + systime_t time; + DnsCacheEntry *entry; + + //Get current time + time = osGetSystemTime(); + + //Go through DNS cache + for(i = 0; i < DNS_CACHE_SIZE; i++) + { + //Point to the current entry + entry = &dnsCache[i]; + + //Name resolution in progress? + if(entry->state == DNS_STATE_IN_PROGRESS) + { + //The request timed out? + if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) + { + //Check whether the maximum number of retransmissions has been exceeded + if(entry->retransmitCount > 0) + { +#if (DNS_CLIENT_SUPPORT == ENABLED) + //DNS resolver? + if(entry->protocol == HOST_NAME_RESOLVER_DNS) + { + //Retransmit DNS query + error = dnsSendQuery(entry); + } + else +#endif +#if (MDNS_CLIENT_SUPPORT == ENABLED) + //mDNS resolver? + if(entry->protocol == HOST_NAME_RESOLVER_MDNS) + { + //Retransmit mDNS query + error = mdnsClientSendQuery(entry); + } + else +#endif +#if (NBNS_CLIENT_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED) + //NetBIOS Name Service resolver? + if(entry->protocol == HOST_NAME_RESOLVER_NBNS) + { + //Retransmit NBNS query + error = nbnsSendQuery(entry); + } + else +#endif + //Unknown protocol? + { + error = ERROR_FAILURE; + } + + //Query message successfully sent? + if(!error) + { + //Save the time at which the query message was sent + entry->timestamp = time; + //The timeout value is doubled for each subsequent retransmission + entry->timeout = MIN(entry->timeout * 2, entry->maxTimeout); + //Decrement retransmission counter + entry->retransmitCount--; + } + else + { + //The entry should be deleted since name resolution has failed + dnsDeleteEntry(entry); + } + } +#if (DNS_CLIENT_SUPPORT == ENABLED) + //DNS resolver? + else if(entry->protocol == HOST_NAME_RESOLVER_DNS) + { + //Select the next DNS server + entry->dnsServerNum++; + //Initialize retransmission counter + entry->retransmitCount = DNS_CLIENT_MAX_RETRIES; + //Send DNS query + error = dnsSendQuery(entry); + + //DNS message successfully sent? + if(!error) + { + //Save the time at which the query message was sent + entry->timestamp = time; + //Set timeout value + entry->timeout = DNS_CLIENT_INIT_TIMEOUT; + //Decrement retransmission counter + entry->retransmitCount--; + } + else + { + //The entry should be deleted since name resolution has failed + dnsDeleteEntry(entry); + } + } +#endif + else + { + //The maximum number of retransmissions has been exceeded + dnsDeleteEntry(entry); + } + } + } + //Name successfully resolved? + else if(entry->state == DNS_STATE_RESOLVED) + { + //Check the lifetime of the current DNS cache entry + if(timeCompare(time, entry->timestamp + entry->timeout) >= 0) + { + //Periodically time out DNS cache entries + dnsDeleteEntry(entry); + } + } + } +} + +#endif +