Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
mdns_client.c
00001 /** 00002 * @file mdns_client.c 00003 * @brief mDNS client (Multicast DNS) 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 MDNS_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "ipv6/ipv6.h" 00035 #include "ipv6/ipv6_misc.h" 00036 #include "mdns/mdns_client.h" 00037 #include "mdns/mdns_responder.h" 00038 #include "mdns/mdns_common.h" 00039 #include "dns/dns_debug.h" 00040 #include "debug.h" 00041 00042 //Check TCP/IP stack configuration 00043 #if (MDNS_CLIENT_SUPPORT == ENABLED) 00044 00045 00046 /** 00047 * @brief Resolve a host name using mDNS 00048 * @param[in] interface Underlying network interface 00049 * @param[in] name Name of the host to be resolved 00050 * @param[in] type Host type (IPv4 or IPv6) 00051 * @param[out] ipAddr IP address corresponding to the specified host name 00052 **/ 00053 00054 error_t mdnsClientResolve(NetInterface *interface, 00055 const char_t *name, HostType type, IpAddr *ipAddr) 00056 { 00057 error_t error; 00058 DnsCacheEntry *entry; 00059 00060 #if (NET_RTOS_SUPPORT == ENABLED) 00061 systime_t delay; 00062 00063 //Debug message 00064 TRACE_INFO("Resolving host name %s (mDNS resolver)...\r\n", name); 00065 #endif 00066 00067 //Get exclusive access 00068 osAcquireMutex(&netMutex); 00069 00070 //Search the DNS cache for the specified host name 00071 entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_MDNS); 00072 00073 //Check whether a matching entry has been found 00074 if(entry) 00075 { 00076 //Host name already resolved? 00077 if(entry->state == DNS_STATE_RESOLVED || 00078 entry->state == DNS_STATE_PERMANENT) 00079 { 00080 //Return the corresponding IP address 00081 *ipAddr = entry->ipAddr; 00082 //Successful host name resolution 00083 error = NO_ERROR; 00084 } 00085 else 00086 { 00087 //Host name resolution is in progress... 00088 error = ERROR_IN_PROGRESS; 00089 } 00090 } 00091 else 00092 { 00093 //If no entry exists, then create a new one 00094 entry = dnsCreateEntry(); 00095 00096 //Record the host name whose IP address is unknown 00097 strcpy(entry->name, name); 00098 00099 //Initialize DNS cache entry 00100 entry->type = type; 00101 entry->protocol = HOST_NAME_RESOLVER_MDNS; 00102 entry->interface = interface; 00103 00104 //Initialize retransmission counter 00105 entry->retransmitCount = MDNS_CLIENT_MAX_RETRIES; 00106 //Send mDNS query 00107 error = mdnsClientSendQuery(entry); 00108 00109 //mDNS message successfully sent? 00110 if(!error) 00111 { 00112 //Save the time at which the query message was sent 00113 entry->timestamp = osGetSystemTime(); 00114 //Set timeout value 00115 entry->timeout = MDNS_CLIENT_INIT_TIMEOUT; 00116 entry->maxTimeout = MDNS_CLIENT_MAX_TIMEOUT; 00117 //Decrement retransmission counter 00118 entry->retransmitCount--; 00119 00120 //Switch state 00121 entry->state = DNS_STATE_IN_PROGRESS; 00122 //Host name resolution is in progress 00123 error = ERROR_IN_PROGRESS; 00124 } 00125 } 00126 00127 //Release exclusive access 00128 osReleaseMutex(&netMutex); 00129 00130 #if (NET_RTOS_SUPPORT == ENABLED) 00131 //Set default polling interval 00132 delay = DNS_CACHE_INIT_POLLING_INTERVAL; 00133 00134 //Wait the host name resolution to complete 00135 while(error == ERROR_IN_PROGRESS) 00136 { 00137 //Wait until the next polling period 00138 osDelayTask(delay); 00139 00140 //Get exclusive access 00141 osAcquireMutex(&netMutex); 00142 00143 //Search the DNS cache for the specified host name 00144 entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_MDNS); 00145 00146 //Check whether a matching entry has been found 00147 if(entry) 00148 { 00149 //Host name successfully resolved? 00150 if(entry->state == DNS_STATE_RESOLVED) 00151 { 00152 //Return the corresponding IP address 00153 *ipAddr = entry->ipAddr; 00154 //Successful host name resolution 00155 error = NO_ERROR; 00156 } 00157 } 00158 else 00159 { 00160 //Host name resolution failed 00161 error = ERROR_FAILURE; 00162 } 00163 00164 //Release exclusive access 00165 osReleaseMutex(&netMutex); 00166 00167 //Backoff support for less aggressive polling 00168 delay = MIN(delay * 2, DNS_CACHE_MAX_POLLING_INTERVAL); 00169 } 00170 00171 //Check status code 00172 if(error) 00173 { 00174 //Failed to resolve host name 00175 TRACE_INFO("Host name resolution failed!\r\n"); 00176 } 00177 else 00178 { 00179 //Successful host name resolution 00180 TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL)); 00181 } 00182 #endif 00183 00184 //Return status code 00185 return error; 00186 } 00187 00188 00189 /** 00190 * @brief Send a mDNS query message 00191 * @param[in] entry Pointer to a valid DNS cache entry 00192 * @return Error code 00193 **/ 00194 00195 error_t mdnsClientSendQuery(DnsCacheEntry *entry) 00196 { 00197 error_t error; 00198 DnsQuestion *dnsQuestion; 00199 MdnsMessage message; 00200 00201 //Create an empty mDNS query message 00202 error = mdnsCreateMessage(&message, FALSE); 00203 //Any error to report? 00204 if(error) 00205 return error; 00206 00207 //Encode the host name using the DNS name notation 00208 message.length += dnsEncodeName(entry->name, message.dnsHeader->questions); 00209 00210 //Point to the corresponding question structure 00211 dnsQuestion = DNS_GET_QUESTION(message.dnsHeader, message.length); 00212 00213 #if (IPV4_SUPPORT == ENABLED) 00214 //An IPv4 address is expected? 00215 if(entry->type == HOST_TYPE_IPV4) 00216 { 00217 //Fill in question structure 00218 dnsQuestion->qtype = HTONS(DNS_RR_TYPE_A); 00219 dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN); 00220 } 00221 #endif 00222 #if (IPV6_SUPPORT == ENABLED) 00223 //An IPv6 address is expected? 00224 if(entry->type == HOST_TYPE_IPV6) 00225 { 00226 //Fill in question structure 00227 dnsQuestion->qtype = HTONS(DNS_RR_TYPE_AAAA); 00228 dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN); 00229 } 00230 #endif 00231 00232 //Update the length of the mDNS query message 00233 message.length += sizeof(DnsQuestion); 00234 //Number of questions in the Question Section 00235 message.dnsHeader->qdcount = 1; 00236 00237 //Send mDNS message 00238 error = mdnsSendMessage(entry->interface, &message, NULL, MDNS_PORT); 00239 00240 //Free previously allocated memory 00241 mdnsDeleteMessage(&message); 00242 00243 //Return status code 00244 return error; 00245 } 00246 00247 00248 /** 00249 * @brief Parse a resource record from the Answer Section 00250 * @param[in] interface Underlying network interface 00251 * @param[in] message Pointer to the mDNS message 00252 * @param[in] offset Offset to first byte of the resource record 00253 * @param[in] record Pointer to the resource record 00254 **/ 00255 00256 void mdnsClientParseAnRecord(NetInterface *interface, 00257 const MdnsMessage *message, size_t offset, const DnsResourceRecord *record) 00258 { 00259 uint_t i; 00260 uint16_t rclass; 00261 DnsCacheEntry *entry; 00262 00263 //Loop through DNS cache entries 00264 for(i = 0; i < DNS_CACHE_SIZE; i++) 00265 { 00266 //Point to the current entry 00267 entry = &dnsCache[i]; 00268 00269 //mDNS name resolution in progress? 00270 if(entry->state == DNS_STATE_IN_PROGRESS && 00271 entry->protocol == HOST_NAME_RESOLVER_MDNS) 00272 { 00273 //Compare resource record name 00274 if(!dnsCompareName(message->dnsHeader, message->length, offset, entry->name, 0)) 00275 { 00276 //Convert the class to host byte order 00277 rclass = ntohs(record->rclass); 00278 //Discard Cache Flush flag 00279 rclass &= ~MDNS_RCLASS_CACHE_FLUSH; 00280 00281 //Check the class of the resource record 00282 if(rclass == DNS_RR_CLASS_IN) 00283 { 00284 #if (IPV4_SUPPORT == ENABLED) 00285 //IPv4 address expected? 00286 if(entry->type == HOST_TYPE_IPV4) 00287 { 00288 //A resource record found? 00289 if(ntohs(record->rtype) == DNS_RR_TYPE_A) 00290 { 00291 //Verify the length of the data field 00292 if(ntohs(record->rdlength) == sizeof(Ipv4Addr)) 00293 { 00294 //Copy the IPv4 address 00295 entry->ipAddr.length = sizeof(Ipv4Addr); 00296 ipv4CopyAddr(&entry->ipAddr.ipv4Addr, record->rdata); 00297 00298 //Save current time 00299 entry->timestamp = osGetSystemTime(); 00300 //Save TTL value 00301 entry->timeout = ntohl(record->ttl) * 1000; 00302 //Limit the lifetime of the mDNS cache entries 00303 entry->timeout = MIN(entry->timeout, MDNS_MAX_LIFETIME); 00304 00305 //Host name successfully resolved 00306 entry->state = DNS_STATE_RESOLVED; 00307 } 00308 } 00309 } 00310 #endif 00311 #if (IPV6_SUPPORT == ENABLED) 00312 //IPv6 address expected? 00313 if(entry->type == HOST_TYPE_IPV6) 00314 { 00315 //AAAA resource record found? 00316 if(ntohs(record->rtype) == DNS_RR_TYPE_AAAA) 00317 { 00318 //Verify the length of the data field 00319 if(ntohs(record->rdlength) == sizeof(Ipv6Addr)) 00320 { 00321 //Copy the IPv6 address 00322 entry->ipAddr.length = sizeof(Ipv6Addr); 00323 ipv6CopyAddr(&entry->ipAddr.ipv6Addr, record->rdata); 00324 00325 //Save current time 00326 entry->timestamp = osGetSystemTime(); 00327 //Save TTL value 00328 entry->timeout = ntohl(record->ttl) * 1000; 00329 //Limit the lifetime of the mDNS cache entries 00330 entry->timeout = MIN(entry->timeout, MDNS_MAX_LIFETIME); 00331 00332 //Host name successfully resolved 00333 entry->state = DNS_STATE_RESOLVED; 00334 } 00335 } 00336 } 00337 #endif 00338 } 00339 } 00340 } 00341 } 00342 } 00343 00344 #endif 00345
Generated on Tue Jul 12 2022 17:10:14 by
1.7.2