Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:10:13 by
