Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file dns_client.c
Sergunb 0:8918a71cdbe9 3 * @brief DNS client (Domain Name System)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL DNS_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include "core/net.h"
Sergunb 0:8918a71cdbe9 34 #include "dns/dns_cache.h"
Sergunb 0:8918a71cdbe9 35 #include "dns/dns_client.h"
Sergunb 0:8918a71cdbe9 36 #include "dns/dns_common.h"
Sergunb 0:8918a71cdbe9 37 #include "dns/dns_debug.h"
Sergunb 0:8918a71cdbe9 38 #include "debug.h"
Sergunb 0:8918a71cdbe9 39
Sergunb 0:8918a71cdbe9 40 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 41 #if (DNS_CLIENT_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 42
Sergunb 0:8918a71cdbe9 43
Sergunb 0:8918a71cdbe9 44 /**
Sergunb 0:8918a71cdbe9 45 * @brief Resolve a host name using DNS
Sergunb 0:8918a71cdbe9 46 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 47 * @param[in] name Name of the host to be resolved
Sergunb 0:8918a71cdbe9 48 * @param[in] type Host type (IPv4 or IPv6)
Sergunb 0:8918a71cdbe9 49 * @param[out] ipAddr IP address corresponding to the specified host name
Sergunb 0:8918a71cdbe9 50 **/
Sergunb 0:8918a71cdbe9 51
Sergunb 0:8918a71cdbe9 52 error_t dnsResolve(NetInterface *interface,
Sergunb 0:8918a71cdbe9 53 const char_t *name, HostType type, IpAddr *ipAddr)
Sergunb 0:8918a71cdbe9 54 {
Sergunb 0:8918a71cdbe9 55 error_t error;
Sergunb 0:8918a71cdbe9 56 DnsCacheEntry *entry;
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58 #if (NET_RTOS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 59 systime_t delay;
Sergunb 0:8918a71cdbe9 60
Sergunb 0:8918a71cdbe9 61 //Debug message
Sergunb 0:8918a71cdbe9 62 TRACE_INFO("Resolving host name %s (DNS resolver)...\r\n", name);
Sergunb 0:8918a71cdbe9 63 #endif
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 //Get exclusive access
Sergunb 0:8918a71cdbe9 66 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 67
Sergunb 0:8918a71cdbe9 68 //Search the DNS cache for the specified host name
Sergunb 0:8918a71cdbe9 69 entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_DNS);
Sergunb 0:8918a71cdbe9 70
Sergunb 0:8918a71cdbe9 71 //Check whether a matching entry has been found
Sergunb 0:8918a71cdbe9 72 if(entry)
Sergunb 0:8918a71cdbe9 73 {
Sergunb 0:8918a71cdbe9 74 //Host name already resolved?
Sergunb 0:8918a71cdbe9 75 if(entry->state == DNS_STATE_RESOLVED ||
Sergunb 0:8918a71cdbe9 76 entry->state == DNS_STATE_PERMANENT)
Sergunb 0:8918a71cdbe9 77 {
Sergunb 0:8918a71cdbe9 78 //Return the corresponding IP address
Sergunb 0:8918a71cdbe9 79 *ipAddr = entry->ipAddr;
Sergunb 0:8918a71cdbe9 80 //Successful host name resolution
Sergunb 0:8918a71cdbe9 81 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 82 }
Sergunb 0:8918a71cdbe9 83 else
Sergunb 0:8918a71cdbe9 84 {
Sergunb 0:8918a71cdbe9 85 //Host name resolution is in progress...
Sergunb 0:8918a71cdbe9 86 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 87 }
Sergunb 0:8918a71cdbe9 88 }
Sergunb 0:8918a71cdbe9 89 else
Sergunb 0:8918a71cdbe9 90 {
Sergunb 0:8918a71cdbe9 91 //If no entry exists, then create a new one
Sergunb 0:8918a71cdbe9 92 entry = dnsCreateEntry();
Sergunb 0:8918a71cdbe9 93
Sergunb 0:8918a71cdbe9 94 //Record the host name whose IP address is unknown
Sergunb 0:8918a71cdbe9 95 strcpy(entry->name, name);
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 //Initialize DNS cache entry
Sergunb 0:8918a71cdbe9 98 entry->type = type;
Sergunb 0:8918a71cdbe9 99 entry->protocol = HOST_NAME_RESOLVER_DNS;
Sergunb 0:8918a71cdbe9 100 entry->interface = interface;
Sergunb 0:8918a71cdbe9 101 //Select primary DNS server
Sergunb 0:8918a71cdbe9 102 entry->dnsServerNum = 0;
Sergunb 0:8918a71cdbe9 103 //Get an ephemeral port number
Sergunb 0:8918a71cdbe9 104 entry->port = udpGetDynamicPort();
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 //An identifier is used by the DNS client to match replies
Sergunb 0:8918a71cdbe9 107 //with corresponding requests
Sergunb 0:8918a71cdbe9 108 entry->id = netGetRand();
Sergunb 0:8918a71cdbe9 109
Sergunb 0:8918a71cdbe9 110 //Callback function to be called when a DNS response is received
Sergunb 0:8918a71cdbe9 111 error = udpAttachRxCallback(interface, entry->port, dnsProcessResponse, NULL);
Sergunb 0:8918a71cdbe9 112
Sergunb 0:8918a71cdbe9 113 //Check status code
Sergunb 0:8918a71cdbe9 114 if(!error)
Sergunb 0:8918a71cdbe9 115 {
Sergunb 0:8918a71cdbe9 116 //Initialize retransmission counter
Sergunb 0:8918a71cdbe9 117 entry->retransmitCount = DNS_CLIENT_MAX_RETRIES;
Sergunb 0:8918a71cdbe9 118 //Send DNS query
Sergunb 0:8918a71cdbe9 119 error = dnsSendQuery(entry);
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121 //DNS message successfully sent?
Sergunb 0:8918a71cdbe9 122 if(!error)
Sergunb 0:8918a71cdbe9 123 {
Sergunb 0:8918a71cdbe9 124 //Save the time at which the query message was sent
Sergunb 0:8918a71cdbe9 125 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 126 //Set timeout value
Sergunb 0:8918a71cdbe9 127 entry->timeout = DNS_CLIENT_INIT_TIMEOUT;
Sergunb 0:8918a71cdbe9 128 entry->maxTimeout = DNS_CLIENT_MAX_TIMEOUT;
Sergunb 0:8918a71cdbe9 129 //Decrement retransmission counter
Sergunb 0:8918a71cdbe9 130 entry->retransmitCount--;
Sergunb 0:8918a71cdbe9 131
Sergunb 0:8918a71cdbe9 132 //Switch state
Sergunb 0:8918a71cdbe9 133 entry->state = DNS_STATE_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 134 //Host name resolution is in progress
Sergunb 0:8918a71cdbe9 135 error = ERROR_IN_PROGRESS;
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137 else
Sergunb 0:8918a71cdbe9 138 {
Sergunb 0:8918a71cdbe9 139 //Unregister callback function
Sergunb 0:8918a71cdbe9 140 udpDetachRxCallback(interface, entry->port);
Sergunb 0:8918a71cdbe9 141 }
Sergunb 0:8918a71cdbe9 142 }
Sergunb 0:8918a71cdbe9 143 }
Sergunb 0:8918a71cdbe9 144
Sergunb 0:8918a71cdbe9 145 //Release exclusive access
Sergunb 0:8918a71cdbe9 146 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 147
Sergunb 0:8918a71cdbe9 148 #if (NET_RTOS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 149 //Set default polling interval
Sergunb 0:8918a71cdbe9 150 delay = DNS_CACHE_INIT_POLLING_INTERVAL;
Sergunb 0:8918a71cdbe9 151
Sergunb 0:8918a71cdbe9 152 //Wait the host name resolution to complete
Sergunb 0:8918a71cdbe9 153 while(error == ERROR_IN_PROGRESS)
Sergunb 0:8918a71cdbe9 154 {
Sergunb 0:8918a71cdbe9 155 //Wait until the next polling period
Sergunb 0:8918a71cdbe9 156 osDelayTask(delay);
Sergunb 0:8918a71cdbe9 157
Sergunb 0:8918a71cdbe9 158 //Get exclusive access
Sergunb 0:8918a71cdbe9 159 osAcquireMutex(&netMutex);
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161 //Search the DNS cache for the specified host name
Sergunb 0:8918a71cdbe9 162 entry = dnsFindEntry(interface, name, type, HOST_NAME_RESOLVER_DNS);
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164 //Check whether a matching entry has been found
Sergunb 0:8918a71cdbe9 165 if(entry)
Sergunb 0:8918a71cdbe9 166 {
Sergunb 0:8918a71cdbe9 167 //Host name successfully resolved?
Sergunb 0:8918a71cdbe9 168 if(entry->state == DNS_STATE_RESOLVED)
Sergunb 0:8918a71cdbe9 169 {
Sergunb 0:8918a71cdbe9 170 //Return the corresponding IP address
Sergunb 0:8918a71cdbe9 171 *ipAddr = entry->ipAddr;
Sergunb 0:8918a71cdbe9 172 //Successful host name resolution
Sergunb 0:8918a71cdbe9 173 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 174 }
Sergunb 0:8918a71cdbe9 175 }
Sergunb 0:8918a71cdbe9 176 else
Sergunb 0:8918a71cdbe9 177 {
Sergunb 0:8918a71cdbe9 178 //Host name resolution failed
Sergunb 0:8918a71cdbe9 179 error = ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 180 }
Sergunb 0:8918a71cdbe9 181
Sergunb 0:8918a71cdbe9 182 //Release exclusive access
Sergunb 0:8918a71cdbe9 183 osReleaseMutex(&netMutex);
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Backoff support for less aggressive polling
Sergunb 0:8918a71cdbe9 186 delay = MIN(delay * 2, DNS_CACHE_MAX_POLLING_INTERVAL);
Sergunb 0:8918a71cdbe9 187 }
Sergunb 0:8918a71cdbe9 188
Sergunb 0:8918a71cdbe9 189 //Check status code
Sergunb 0:8918a71cdbe9 190 if(error)
Sergunb 0:8918a71cdbe9 191 {
Sergunb 0:8918a71cdbe9 192 //Failed to resolve host name
Sergunb 0:8918a71cdbe9 193 TRACE_INFO("Host name resolution failed!\r\n");
Sergunb 0:8918a71cdbe9 194 }
Sergunb 0:8918a71cdbe9 195 else
Sergunb 0:8918a71cdbe9 196 {
Sergunb 0:8918a71cdbe9 197 //Successful host name resolution
Sergunb 0:8918a71cdbe9 198 TRACE_INFO("Host name resolved to %s...\r\n", ipAddrToString(ipAddr, NULL));
Sergunb 0:8918a71cdbe9 199 }
Sergunb 0:8918a71cdbe9 200 #endif
Sergunb 0:8918a71cdbe9 201
Sergunb 0:8918a71cdbe9 202 //Return status code
Sergunb 0:8918a71cdbe9 203 return error;
Sergunb 0:8918a71cdbe9 204 }
Sergunb 0:8918a71cdbe9 205
Sergunb 0:8918a71cdbe9 206
Sergunb 0:8918a71cdbe9 207 /**
Sergunb 0:8918a71cdbe9 208 * @brief Send a DNS query message
Sergunb 0:8918a71cdbe9 209 * @param[in] entry Pointer to a valid DNS cache entry
Sergunb 0:8918a71cdbe9 210 * @return Error code
Sergunb 0:8918a71cdbe9 211 **/
Sergunb 0:8918a71cdbe9 212
Sergunb 0:8918a71cdbe9 213 error_t dnsSendQuery(DnsCacheEntry *entry)
Sergunb 0:8918a71cdbe9 214 {
Sergunb 0:8918a71cdbe9 215 error_t error;
Sergunb 0:8918a71cdbe9 216 size_t length;
Sergunb 0:8918a71cdbe9 217 size_t offset;
Sergunb 0:8918a71cdbe9 218 NetBuffer *buffer;
Sergunb 0:8918a71cdbe9 219 DnsHeader *message;
Sergunb 0:8918a71cdbe9 220 DnsQuestion *dnsQuestion;
Sergunb 0:8918a71cdbe9 221 IpAddr destIpAddr;
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 224 //An IPv4 address is expected?
Sergunb 0:8918a71cdbe9 225 if(entry->type == HOST_TYPE_IPV4)
Sergunb 0:8918a71cdbe9 226 {
Sergunb 0:8918a71cdbe9 227 //Point to the IPv4 context
Sergunb 0:8918a71cdbe9 228 Ipv4Context *ipv4Context = &entry->interface->ipv4Context;
Sergunb 0:8918a71cdbe9 229
Sergunb 0:8918a71cdbe9 230 //Out of range index?
Sergunb 0:8918a71cdbe9 231 if(entry->dnsServerNum >= IPV4_DNS_SERVER_LIST_SIZE)
Sergunb 0:8918a71cdbe9 232 return ERROR_NO_DNS_SERVER;
Sergunb 0:8918a71cdbe9 233
Sergunb 0:8918a71cdbe9 234 //Select the relevant DNS server
Sergunb 0:8918a71cdbe9 235 destIpAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 236 destIpAddr.ipv4Addr = ipv4Context->dnsServerList[entry->dnsServerNum];
Sergunb 0:8918a71cdbe9 237
Sergunb 0:8918a71cdbe9 238 //Make sure the IP address is valid
Sergunb 0:8918a71cdbe9 239 if(destIpAddr.ipv4Addr == IPV4_UNSPECIFIED_ADDR)
Sergunb 0:8918a71cdbe9 240 return ERROR_NO_DNS_SERVER;
Sergunb 0:8918a71cdbe9 241 }
Sergunb 0:8918a71cdbe9 242 else
Sergunb 0:8918a71cdbe9 243 #endif
Sergunb 0:8918a71cdbe9 244 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 245 //An IPv6 address is expected?
Sergunb 0:8918a71cdbe9 246 if(entry->type == HOST_TYPE_IPV6)
Sergunb 0:8918a71cdbe9 247 {
Sergunb 0:8918a71cdbe9 248 //Point to the IPv6 context
Sergunb 0:8918a71cdbe9 249 Ipv6Context *ipv6Context = &entry->interface->ipv6Context;
Sergunb 0:8918a71cdbe9 250
Sergunb 0:8918a71cdbe9 251 //Out of range index?
Sergunb 0:8918a71cdbe9 252 if(entry->dnsServerNum >= IPV6_DNS_SERVER_LIST_SIZE)
Sergunb 0:8918a71cdbe9 253 return ERROR_NO_DNS_SERVER;
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Select the relevant DNS server
Sergunb 0:8918a71cdbe9 256 destIpAddr.length = sizeof(Ipv6Addr);
Sergunb 0:8918a71cdbe9 257 destIpAddr.ipv6Addr = ipv6Context->dnsServerList[entry->dnsServerNum];
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Make sure the IP address is valid
Sergunb 0:8918a71cdbe9 260 if(ipv6CompAddr(&destIpAddr.ipv6Addr, &IPV6_UNSPECIFIED_ADDR))
Sergunb 0:8918a71cdbe9 261 return ERROR_NO_DNS_SERVER;
Sergunb 0:8918a71cdbe9 262 }
Sergunb 0:8918a71cdbe9 263 else
Sergunb 0:8918a71cdbe9 264 #endif
Sergunb 0:8918a71cdbe9 265 //Invalid host type?
Sergunb 0:8918a71cdbe9 266 {
Sergunb 0:8918a71cdbe9 267 //Report an error
Sergunb 0:8918a71cdbe9 268 return ERROR_INVALID_PARAMETER;
Sergunb 0:8918a71cdbe9 269 }
Sergunb 0:8918a71cdbe9 270
Sergunb 0:8918a71cdbe9 271 //Allocate a memory buffer to hold the DNS query message
Sergunb 0:8918a71cdbe9 272 buffer = udpAllocBuffer(DNS_MESSAGE_MAX_SIZE, &offset);
Sergunb 0:8918a71cdbe9 273 //Failed to allocate buffer?
Sergunb 0:8918a71cdbe9 274 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 275 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 276
Sergunb 0:8918a71cdbe9 277 //Point to the DNS header
Sergunb 0:8918a71cdbe9 278 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 //Format DNS query message
Sergunb 0:8918a71cdbe9 281 message->id = htons(entry->id);
Sergunb 0:8918a71cdbe9 282 message->qr = 0;
Sergunb 0:8918a71cdbe9 283 message->opcode = DNS_OPCODE_QUERY;
Sergunb 0:8918a71cdbe9 284 message->aa = 0;
Sergunb 0:8918a71cdbe9 285 message->tc = 0;
Sergunb 0:8918a71cdbe9 286 message->rd = 1;
Sergunb 0:8918a71cdbe9 287 message->ra = 0;
Sergunb 0:8918a71cdbe9 288 message->z = 0;
Sergunb 0:8918a71cdbe9 289 message->rcode = DNS_RCODE_NO_ERROR;
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 //The DNS query contains one question
Sergunb 0:8918a71cdbe9 292 message->qdcount = HTONS(1);
Sergunb 0:8918a71cdbe9 293 message->ancount = 0;
Sergunb 0:8918a71cdbe9 294 message->nscount = 0;
Sergunb 0:8918a71cdbe9 295 message->arcount = 0;
Sergunb 0:8918a71cdbe9 296
Sergunb 0:8918a71cdbe9 297 //Length of the DNS query message
Sergunb 0:8918a71cdbe9 298 length = sizeof(DnsHeader);
Sergunb 0:8918a71cdbe9 299
Sergunb 0:8918a71cdbe9 300 //Encode the host name using the DNS name notation
Sergunb 0:8918a71cdbe9 301 length += dnsEncodeName(entry->name, message->questions);
Sergunb 0:8918a71cdbe9 302
Sergunb 0:8918a71cdbe9 303 //Point to the corresponding question structure
Sergunb 0:8918a71cdbe9 304 dnsQuestion = DNS_GET_QUESTION(message, length);
Sergunb 0:8918a71cdbe9 305
Sergunb 0:8918a71cdbe9 306 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 307 //An IPv4 address is expected?
Sergunb 0:8918a71cdbe9 308 if(entry->type == HOST_TYPE_IPV4)
Sergunb 0:8918a71cdbe9 309 {
Sergunb 0:8918a71cdbe9 310 //Fill in question structure
Sergunb 0:8918a71cdbe9 311 dnsQuestion->qtype = HTONS(DNS_RR_TYPE_A);
Sergunb 0:8918a71cdbe9 312 dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN);
Sergunb 0:8918a71cdbe9 313 }
Sergunb 0:8918a71cdbe9 314 #endif
Sergunb 0:8918a71cdbe9 315 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 316 //An IPv6 address is expected?
Sergunb 0:8918a71cdbe9 317 if(entry->type == HOST_TYPE_IPV6)
Sergunb 0:8918a71cdbe9 318 {
Sergunb 0:8918a71cdbe9 319 //Fill in question structure
Sergunb 0:8918a71cdbe9 320 dnsQuestion->qtype = HTONS(DNS_RR_TYPE_AAAA);
Sergunb 0:8918a71cdbe9 321 dnsQuestion->qclass = HTONS(DNS_RR_CLASS_IN);
Sergunb 0:8918a71cdbe9 322 }
Sergunb 0:8918a71cdbe9 323 #endif
Sergunb 0:8918a71cdbe9 324
Sergunb 0:8918a71cdbe9 325 //Update the length of the DNS query message
Sergunb 0:8918a71cdbe9 326 length += sizeof(DnsQuestion);
Sergunb 0:8918a71cdbe9 327
Sergunb 0:8918a71cdbe9 328 //Adjust the length of the multi-part buffer
Sergunb 0:8918a71cdbe9 329 netBufferSetLength(buffer, offset + length);
Sergunb 0:8918a71cdbe9 330
Sergunb 0:8918a71cdbe9 331 //Debug message
Sergunb 0:8918a71cdbe9 332 TRACE_INFO("Sending DNS message (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 333 //Dump message
Sergunb 0:8918a71cdbe9 334 dnsDumpMessage(message, length);
Sergunb 0:8918a71cdbe9 335
Sergunb 0:8918a71cdbe9 336 //Send DNS query message
Sergunb 0:8918a71cdbe9 337 error = udpSendDatagramEx(entry->interface, entry->port,
Sergunb 0:8918a71cdbe9 338 &destIpAddr, DNS_PORT, buffer, offset, 0);
Sergunb 0:8918a71cdbe9 339
Sergunb 0:8918a71cdbe9 340 //Free previously allocated memory
Sergunb 0:8918a71cdbe9 341 netBufferFree(buffer);
Sergunb 0:8918a71cdbe9 342 //Return status code
Sergunb 0:8918a71cdbe9 343 return error;
Sergunb 0:8918a71cdbe9 344 }
Sergunb 0:8918a71cdbe9 345
Sergunb 0:8918a71cdbe9 346
Sergunb 0:8918a71cdbe9 347 /**
Sergunb 0:8918a71cdbe9 348 * @brief Process incoming DNS response message
Sergunb 0:8918a71cdbe9 349 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 350 * @param[in] pseudoHeader UDP pseudo header
Sergunb 0:8918a71cdbe9 351 * @param[in] udpHeader UDP header
Sergunb 0:8918a71cdbe9 352 * @param[in] buffer Multi-part buffer containing the incoming DNS message
Sergunb 0:8918a71cdbe9 353 * @param[in] offset Offset to the first byte of the DNS message
Sergunb 0:8918a71cdbe9 354 * @param[in] params Callback function parameter (not used)
Sergunb 0:8918a71cdbe9 355 **/
Sergunb 0:8918a71cdbe9 356
Sergunb 0:8918a71cdbe9 357 void dnsProcessResponse(NetInterface *interface, const IpPseudoHeader *pseudoHeader,
Sergunb 0:8918a71cdbe9 358 const UdpHeader *udpHeader, const NetBuffer *buffer, size_t offset, void *params)
Sergunb 0:8918a71cdbe9 359 {
Sergunb 0:8918a71cdbe9 360 uint_t i;
Sergunb 0:8918a71cdbe9 361 uint_t j;
Sergunb 0:8918a71cdbe9 362 size_t pos;
Sergunb 0:8918a71cdbe9 363 size_t length;
Sergunb 0:8918a71cdbe9 364 DnsHeader *message;
Sergunb 0:8918a71cdbe9 365 DnsQuestion *question;
Sergunb 0:8918a71cdbe9 366 DnsResourceRecord *record;
Sergunb 0:8918a71cdbe9 367 DnsCacheEntry *entry;
Sergunb 0:8918a71cdbe9 368
Sergunb 0:8918a71cdbe9 369 //Retrieve the length of the DNS message
Sergunb 0:8918a71cdbe9 370 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 371
Sergunb 0:8918a71cdbe9 372 //Ensure the DNS message is valid
Sergunb 0:8918a71cdbe9 373 if(length < sizeof(DnsHeader))
Sergunb 0:8918a71cdbe9 374 return;
Sergunb 0:8918a71cdbe9 375 if(length > DNS_MESSAGE_MAX_SIZE)
Sergunb 0:8918a71cdbe9 376 return;
Sergunb 0:8918a71cdbe9 377
Sergunb 0:8918a71cdbe9 378 //Point to the DNS message header
Sergunb 0:8918a71cdbe9 379 message = netBufferAt(buffer, offset);
Sergunb 0:8918a71cdbe9 380 //Sanity check
Sergunb 0:8918a71cdbe9 381 if(message == NULL)
Sergunb 0:8918a71cdbe9 382 return;
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384 //Debug message
Sergunb 0:8918a71cdbe9 385 TRACE_INFO("DNS message received (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 386 //Dump message
Sergunb 0:8918a71cdbe9 387 dnsDumpMessage(message, length);
Sergunb 0:8918a71cdbe9 388
Sergunb 0:8918a71cdbe9 389 //Check message type
Sergunb 0:8918a71cdbe9 390 if(!message->qr)
Sergunb 0:8918a71cdbe9 391 return;
Sergunb 0:8918a71cdbe9 392 //The DNS message shall contain one question
Sergunb 0:8918a71cdbe9 393 if(ntohs(message->qdcount) != 1)
Sergunb 0:8918a71cdbe9 394 return;
Sergunb 0:8918a71cdbe9 395
Sergunb 0:8918a71cdbe9 396 //Loop through DNS cache entries
Sergunb 0:8918a71cdbe9 397 for(i = 0; i < DNS_CACHE_SIZE; i++)
Sergunb 0:8918a71cdbe9 398 {
Sergunb 0:8918a71cdbe9 399 //Point to the current entry
Sergunb 0:8918a71cdbe9 400 entry = &dnsCache[i];
Sergunb 0:8918a71cdbe9 401
Sergunb 0:8918a71cdbe9 402 //DNS name resolution in progress?
Sergunb 0:8918a71cdbe9 403 if(entry->state == DNS_STATE_IN_PROGRESS &&
Sergunb 0:8918a71cdbe9 404 entry->protocol == HOST_NAME_RESOLVER_DNS)
Sergunb 0:8918a71cdbe9 405 {
Sergunb 0:8918a71cdbe9 406 //Check destination port number
Sergunb 0:8918a71cdbe9 407 if(entry->port == ntohs(udpHeader->destPort))
Sergunb 0:8918a71cdbe9 408 {
Sergunb 0:8918a71cdbe9 409 //Compare identifier against the expected one
Sergunb 0:8918a71cdbe9 410 if(ntohs(message->id) != entry->id)
Sergunb 0:8918a71cdbe9 411 break;
Sergunb 0:8918a71cdbe9 412
Sergunb 0:8918a71cdbe9 413 //Point to the first question
Sergunb 0:8918a71cdbe9 414 pos = sizeof(DnsHeader);
Sergunb 0:8918a71cdbe9 415 //Parse domain name
Sergunb 0:8918a71cdbe9 416 pos = dnsParseName(message, length, pos, NULL, 0);
Sergunb 0:8918a71cdbe9 417
Sergunb 0:8918a71cdbe9 418 //Invalid name?
Sergunb 0:8918a71cdbe9 419 if(!pos)
Sergunb 0:8918a71cdbe9 420 break;
Sergunb 0:8918a71cdbe9 421 //Malformed DNS message?
Sergunb 0:8918a71cdbe9 422 if((pos + sizeof(DnsQuestion)) > length)
Sergunb 0:8918a71cdbe9 423 break;
Sergunb 0:8918a71cdbe9 424
Sergunb 0:8918a71cdbe9 425 //Compare domain name
Sergunb 0:8918a71cdbe9 426 if(dnsCompareName(message, length, sizeof(DnsHeader), entry->name, 0))
Sergunb 0:8918a71cdbe9 427 break;
Sergunb 0:8918a71cdbe9 428
Sergunb 0:8918a71cdbe9 429 //Point to the corresponding entry
Sergunb 0:8918a71cdbe9 430 question = DNS_GET_QUESTION(message, pos);
Sergunb 0:8918a71cdbe9 431
Sergunb 0:8918a71cdbe9 432 //Check the class of the query
Sergunb 0:8918a71cdbe9 433 if(ntohs(question->qclass) != DNS_RR_CLASS_IN)
Sergunb 0:8918a71cdbe9 434 break;
Sergunb 0:8918a71cdbe9 435
Sergunb 0:8918a71cdbe9 436 //Check the type of the query
Sergunb 0:8918a71cdbe9 437 if(entry->type == HOST_TYPE_IPV4 && ntohs(question->qtype) != DNS_RR_TYPE_A)
Sergunb 0:8918a71cdbe9 438 break;
Sergunb 0:8918a71cdbe9 439 if(entry->type == HOST_TYPE_IPV6 && ntohs(question->qtype) != DNS_RR_TYPE_AAAA)
Sergunb 0:8918a71cdbe9 440 break;
Sergunb 0:8918a71cdbe9 441
Sergunb 0:8918a71cdbe9 442 //Check return code
Sergunb 0:8918a71cdbe9 443 if(message->rcode != DNS_RCODE_NO_ERROR)
Sergunb 0:8918a71cdbe9 444 {
Sergunb 0:8918a71cdbe9 445 //The entry should be deleted since name resolution has failed
Sergunb 0:8918a71cdbe9 446 dnsDeleteEntry(entry);
Sergunb 0:8918a71cdbe9 447 //Exit immediately
Sergunb 0:8918a71cdbe9 448 break;
Sergunb 0:8918a71cdbe9 449 }
Sergunb 0:8918a71cdbe9 450
Sergunb 0:8918a71cdbe9 451 //Point to the first answer
Sergunb 0:8918a71cdbe9 452 pos += sizeof(DnsQuestion);
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 //Parse answer resource records
Sergunb 0:8918a71cdbe9 455 for(j = 0; j < ntohs(message->ancount); j++)
Sergunb 0:8918a71cdbe9 456 {
Sergunb 0:8918a71cdbe9 457 //Parse domain name
Sergunb 0:8918a71cdbe9 458 pos = dnsParseName(message, length, pos, NULL, 0);
Sergunb 0:8918a71cdbe9 459 //Invalid name?
Sergunb 0:8918a71cdbe9 460 if(!pos)
Sergunb 0:8918a71cdbe9 461 break;
Sergunb 0:8918a71cdbe9 462
Sergunb 0:8918a71cdbe9 463 //Point to the associated resource record
Sergunb 0:8918a71cdbe9 464 record = DNS_GET_RESOURCE_RECORD(message, pos);
Sergunb 0:8918a71cdbe9 465 //Point to the resource data
Sergunb 0:8918a71cdbe9 466 pos += sizeof(DnsResourceRecord);
Sergunb 0:8918a71cdbe9 467
Sergunb 0:8918a71cdbe9 468 //Make sure the resource record is valid
Sergunb 0:8918a71cdbe9 469 if(pos > length)
Sergunb 0:8918a71cdbe9 470 break;
Sergunb 0:8918a71cdbe9 471 if((pos + ntohs(record->rdlength)) > length)
Sergunb 0:8918a71cdbe9 472 break;
Sergunb 0:8918a71cdbe9 473
Sergunb 0:8918a71cdbe9 474 #if (IPV4_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 475 //IPv4 address expected?
Sergunb 0:8918a71cdbe9 476 if(entry->type == HOST_TYPE_IPV4)
Sergunb 0:8918a71cdbe9 477 {
Sergunb 0:8918a71cdbe9 478 //A resource record found?
Sergunb 0:8918a71cdbe9 479 if(ntohs(record->rtype) == DNS_RR_TYPE_A &&
Sergunb 0:8918a71cdbe9 480 ntohs(record->rdlength) == sizeof(Ipv4Addr))
Sergunb 0:8918a71cdbe9 481 {
Sergunb 0:8918a71cdbe9 482 //Copy the IPv4 address
Sergunb 0:8918a71cdbe9 483 entry->ipAddr.length = sizeof(Ipv4Addr);
Sergunb 0:8918a71cdbe9 484 ipv4CopyAddr(&entry->ipAddr.ipv4Addr, record->rdata);
Sergunb 0:8918a71cdbe9 485
Sergunb 0:8918a71cdbe9 486 //Save current time
Sergunb 0:8918a71cdbe9 487 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 488 //Save TTL value
Sergunb 0:8918a71cdbe9 489 entry->timeout = ntohl(record->ttl) * 1000;
Sergunb 0:8918a71cdbe9 490
Sergunb 0:8918a71cdbe9 491 //Limit the lifetime of the DNS cache entries
Sergunb 0:8918a71cdbe9 492 if(entry->timeout >= DNS_MAX_LIFETIME)
Sergunb 0:8918a71cdbe9 493 entry->timeout = DNS_MAX_LIFETIME;
Sergunb 0:8918a71cdbe9 494 if(entry->timeout <= DNS_MIN_LIFETIME)
Sergunb 0:8918a71cdbe9 495 entry->timeout = DNS_MIN_LIFETIME;
Sergunb 0:8918a71cdbe9 496
Sergunb 0:8918a71cdbe9 497 //Unregister UDP callback function
Sergunb 0:8918a71cdbe9 498 udpDetachRxCallback(interface, entry->port);
Sergunb 0:8918a71cdbe9 499 //Host name successfully resolved
Sergunb 0:8918a71cdbe9 500 entry->state = DNS_STATE_RESOLVED;
Sergunb 0:8918a71cdbe9 501 //Exit immediately
Sergunb 0:8918a71cdbe9 502 break;
Sergunb 0:8918a71cdbe9 503 }
Sergunb 0:8918a71cdbe9 504 }
Sergunb 0:8918a71cdbe9 505 #endif
Sergunb 0:8918a71cdbe9 506 #if (IPV6_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 507 //IPv6 address expected?
Sergunb 0:8918a71cdbe9 508 if(entry->type == HOST_TYPE_IPV6)
Sergunb 0:8918a71cdbe9 509 {
Sergunb 0:8918a71cdbe9 510 //AAAA resource record found?
Sergunb 0:8918a71cdbe9 511 if(ntohs(record->rtype) == DNS_RR_TYPE_AAAA &&
Sergunb 0:8918a71cdbe9 512 ntohs(record->rdlength) == sizeof(Ipv6Addr))
Sergunb 0:8918a71cdbe9 513 {
Sergunb 0:8918a71cdbe9 514 //Copy the IPv6 address
Sergunb 0:8918a71cdbe9 515 entry->ipAddr.length = sizeof(Ipv6Addr);
Sergunb 0:8918a71cdbe9 516 ipv6CopyAddr(&entry->ipAddr.ipv6Addr, record->rdata);
Sergunb 0:8918a71cdbe9 517
Sergunb 0:8918a71cdbe9 518 //Save current time
Sergunb 0:8918a71cdbe9 519 entry->timestamp = osGetSystemTime();
Sergunb 0:8918a71cdbe9 520 //Save TTL value
Sergunb 0:8918a71cdbe9 521 entry->timeout = ntohl(record->ttl) * 1000;
Sergunb 0:8918a71cdbe9 522
Sergunb 0:8918a71cdbe9 523 //Limit the lifetime of the DNS cache entries
Sergunb 0:8918a71cdbe9 524 if(entry->timeout >= DNS_MAX_LIFETIME)
Sergunb 0:8918a71cdbe9 525 entry->timeout = DNS_MAX_LIFETIME;
Sergunb 0:8918a71cdbe9 526 if(entry->timeout <= DNS_MIN_LIFETIME)
Sergunb 0:8918a71cdbe9 527 entry->timeout = DNS_MIN_LIFETIME;
Sergunb 0:8918a71cdbe9 528
Sergunb 0:8918a71cdbe9 529 //Unregister UDP callback function
Sergunb 0:8918a71cdbe9 530 udpDetachRxCallback(interface, entry->port);
Sergunb 0:8918a71cdbe9 531 //Host name successfully resolved
Sergunb 0:8918a71cdbe9 532 entry->state = DNS_STATE_RESOLVED;
Sergunb 0:8918a71cdbe9 533 //Exit immediately
Sergunb 0:8918a71cdbe9 534 break;
Sergunb 0:8918a71cdbe9 535 }
Sergunb 0:8918a71cdbe9 536 }
Sergunb 0:8918a71cdbe9 537 #endif
Sergunb 0:8918a71cdbe9 538 //Point to the next resource record
Sergunb 0:8918a71cdbe9 539 pos += ntohs(record->rdlength);
Sergunb 0:8918a71cdbe9 540 }
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542 //We are done
Sergunb 0:8918a71cdbe9 543 break;
Sergunb 0:8918a71cdbe9 544 }
Sergunb 0:8918a71cdbe9 545 }
Sergunb 0:8918a71cdbe9 546 }
Sergunb 0:8918a71cdbe9 547 }
Sergunb 0:8918a71cdbe9 548
Sergunb 0:8918a71cdbe9 549 #endif
Sergunb 0:8918a71cdbe9 550