Used in Live Traffic Update Nokia LCD Display Project

Fork of NetServices by Segundo Equipo

Committer:
rrajan8
Date:
Wed Mar 06 19:07:23 2013 +0000
Revision:
8:92b57208ab99
Parent:
0:ac1725ba162c
This project utilizes mbed's networking features to display live traffic updates on the Nokia LCD using the MapQuest API's Traffic Web Service.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1 /**
segundo 0:ac1725ba162c 2 * @file
segundo 0:ac1725ba162c 3 * DNS - host name to IP address resolver.
segundo 0:ac1725ba162c 4 *
segundo 0:ac1725ba162c 5 */
segundo 0:ac1725ba162c 6
segundo 0:ac1725ba162c 7 /**
segundo 0:ac1725ba162c 8
segundo 0:ac1725ba162c 9 * This file implements a DNS host name to IP address resolver.
segundo 0:ac1725ba162c 10
segundo 0:ac1725ba162c 11 * Port to lwIP from uIP
segundo 0:ac1725ba162c 12 * by Jim Pettinato April 2007
segundo 0:ac1725ba162c 13
segundo 0:ac1725ba162c 14 * uIP version Copyright (c) 2002-2003, Adam Dunkels.
segundo 0:ac1725ba162c 15 * All rights reserved.
segundo 0:ac1725ba162c 16 *
segundo 0:ac1725ba162c 17 * Redistribution and use in source and binary forms, with or without
segundo 0:ac1725ba162c 18 * modification, are permitted provided that the following conditions
segundo 0:ac1725ba162c 19 * are met:
segundo 0:ac1725ba162c 20 * 1. Redistributions of source code must retain the above copyright
segundo 0:ac1725ba162c 21 * notice, this list of conditions and the following disclaimer.
segundo 0:ac1725ba162c 22 * 2. Redistributions in binary form must reproduce the above copyright
segundo 0:ac1725ba162c 23 * notice, this list of conditions and the following disclaimer in the
segundo 0:ac1725ba162c 24 * documentation and/or other materials provided with the distribution.
segundo 0:ac1725ba162c 25 * 3. The name of the author may not be used to endorse or promote
segundo 0:ac1725ba162c 26 * products derived from this software without specific prior
segundo 0:ac1725ba162c 27 * written permission.
segundo 0:ac1725ba162c 28 *
segundo 0:ac1725ba162c 29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
segundo 0:ac1725ba162c 30 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
segundo 0:ac1725ba162c 31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
segundo 0:ac1725ba162c 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
segundo 0:ac1725ba162c 33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
segundo 0:ac1725ba162c 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
segundo 0:ac1725ba162c 35 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
segundo 0:ac1725ba162c 36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
segundo 0:ac1725ba162c 37 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
segundo 0:ac1725ba162c 38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
segundo 0:ac1725ba162c 39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
segundo 0:ac1725ba162c 40 *
segundo 0:ac1725ba162c 41 *
segundo 0:ac1725ba162c 42 * DNS.C
segundo 0:ac1725ba162c 43 *
segundo 0:ac1725ba162c 44 * The lwIP DNS resolver functions are used to lookup a host name and
segundo 0:ac1725ba162c 45 * map it to a numerical IP address. It maintains a list of resolved
segundo 0:ac1725ba162c 46 * hostnames that can be queried with the dns_lookup() function.
segundo 0:ac1725ba162c 47 * New hostnames can be resolved using the dns_query() function.
segundo 0:ac1725ba162c 48 *
segundo 0:ac1725ba162c 49 * The lwIP version of the resolver also adds a non-blocking version of
segundo 0:ac1725ba162c 50 * gethostbyname() that will work with a raw API application. This function
segundo 0:ac1725ba162c 51 * checks for an IP address string first and converts it if it is valid.
segundo 0:ac1725ba162c 52 * gethostbyname() then does a dns_lookup() to see if the name is
segundo 0:ac1725ba162c 53 * already in the table. If so, the IP is returned. If not, a query is
segundo 0:ac1725ba162c 54 * issued and the function returns with a ERR_INPROGRESS status. The app
segundo 0:ac1725ba162c 55 * using the dns client must then go into a waiting state.
segundo 0:ac1725ba162c 56 *
segundo 0:ac1725ba162c 57 * Once a hostname has been resolved (or found to be non-existent),
segundo 0:ac1725ba162c 58 * the resolver code calls a specified callback function (which
segundo 0:ac1725ba162c 59 * must be implemented by the module that uses the resolver).
segundo 0:ac1725ba162c 60 */
segundo 0:ac1725ba162c 61
segundo 0:ac1725ba162c 62 /*-----------------------------------------------------------------------------
segundo 0:ac1725ba162c 63 * RFC 1035 - Domain names - implementation and specification
segundo 0:ac1725ba162c 64 * RFC 2181 - Clarifications to the DNS Specification
segundo 0:ac1725ba162c 65 *----------------------------------------------------------------------------*/
segundo 0:ac1725ba162c 66
segundo 0:ac1725ba162c 67 /** @todo: define good default values (rfc compliance) */
segundo 0:ac1725ba162c 68 /** @todo: improve answer parsing, more checkings... */
segundo 0:ac1725ba162c 69 /** @todo: check RFC1035 - 7.3. Processing responses */
segundo 0:ac1725ba162c 70
segundo 0:ac1725ba162c 71 /*-----------------------------------------------------------------------------
segundo 0:ac1725ba162c 72 * Includes
segundo 0:ac1725ba162c 73 *----------------------------------------------------------------------------*/
segundo 0:ac1725ba162c 74
segundo 0:ac1725ba162c 75 #include "lwip/opt.h"
segundo 0:ac1725ba162c 76
segundo 0:ac1725ba162c 77 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
segundo 0:ac1725ba162c 78
segundo 0:ac1725ba162c 79 #include "lwip/udp.h"
segundo 0:ac1725ba162c 80 #include "lwip/mem.h"
segundo 0:ac1725ba162c 81 #include "lwip/memp.h"
segundo 0:ac1725ba162c 82 #include "lwip/dns.h"
segundo 0:ac1725ba162c 83
segundo 0:ac1725ba162c 84 #include <string.h>
segundo 0:ac1725ba162c 85
segundo 0:ac1725ba162c 86 /** DNS server IP address */
segundo 0:ac1725ba162c 87 #ifndef DNS_SERVER_ADDRESS
segundo 0:ac1725ba162c 88 #define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
segundo 0:ac1725ba162c 89 #endif
segundo 0:ac1725ba162c 90
segundo 0:ac1725ba162c 91 /** DNS server port address */
segundo 0:ac1725ba162c 92 #ifndef DNS_SERVER_PORT
segundo 0:ac1725ba162c 93 #define DNS_SERVER_PORT 53
segundo 0:ac1725ba162c 94 #endif
segundo 0:ac1725ba162c 95
segundo 0:ac1725ba162c 96 /** DNS maximum number of retries when asking for a name, before "timeout". */
segundo 0:ac1725ba162c 97 #ifndef DNS_MAX_RETRIES
segundo 0:ac1725ba162c 98 #define DNS_MAX_RETRIES 4
segundo 0:ac1725ba162c 99 #endif
segundo 0:ac1725ba162c 100
segundo 0:ac1725ba162c 101 /** DNS resource record max. TTL (one week as default) */
segundo 0:ac1725ba162c 102 #ifndef DNS_MAX_TTL
segundo 0:ac1725ba162c 103 #define DNS_MAX_TTL 604800
segundo 0:ac1725ba162c 104 #endif
segundo 0:ac1725ba162c 105
segundo 0:ac1725ba162c 106 /* DNS protocol flags */
segundo 0:ac1725ba162c 107 #define DNS_FLAG1_RESPONSE 0x80
segundo 0:ac1725ba162c 108 #define DNS_FLAG1_OPCODE_STATUS 0x10
segundo 0:ac1725ba162c 109 #define DNS_FLAG1_OPCODE_INVERSE 0x08
segundo 0:ac1725ba162c 110 #define DNS_FLAG1_OPCODE_STANDARD 0x00
segundo 0:ac1725ba162c 111 #define DNS_FLAG1_AUTHORATIVE 0x04
segundo 0:ac1725ba162c 112 #define DNS_FLAG1_TRUNC 0x02
segundo 0:ac1725ba162c 113 #define DNS_FLAG1_RD 0x01
segundo 0:ac1725ba162c 114 #define DNS_FLAG2_RA 0x80
segundo 0:ac1725ba162c 115 #define DNS_FLAG2_ERR_MASK 0x0f
segundo 0:ac1725ba162c 116 #define DNS_FLAG2_ERR_NONE 0x00
segundo 0:ac1725ba162c 117 #define DNS_FLAG2_ERR_NAME 0x03
segundo 0:ac1725ba162c 118
segundo 0:ac1725ba162c 119 /* DNS protocol states */
segundo 0:ac1725ba162c 120 #define DNS_STATE_UNUSED 0
segundo 0:ac1725ba162c 121 #define DNS_STATE_NEW 1
segundo 0:ac1725ba162c 122 #define DNS_STATE_ASKING 2
segundo 0:ac1725ba162c 123 #define DNS_STATE_DONE 3
segundo 0:ac1725ba162c 124
segundo 0:ac1725ba162c 125 #ifdef PACK_STRUCT_USE_INCLUDES
segundo 0:ac1725ba162c 126 # include "arch/bpstruct.h"
segundo 0:ac1725ba162c 127 #endif
segundo 0:ac1725ba162c 128 PACK_STRUCT_BEGIN
segundo 0:ac1725ba162c 129 /** DNS message header */
segundo 0:ac1725ba162c 130 struct dns_hdr {
segundo 0:ac1725ba162c 131 PACK_STRUCT_FIELD(u16_t id);
segundo 0:ac1725ba162c 132 PACK_STRUCT_FIELD(u8_t flags1);
segundo 0:ac1725ba162c 133 PACK_STRUCT_FIELD(u8_t flags2);
segundo 0:ac1725ba162c 134 PACK_STRUCT_FIELD(u16_t numquestions);
segundo 0:ac1725ba162c 135 PACK_STRUCT_FIELD(u16_t numanswers);
segundo 0:ac1725ba162c 136 PACK_STRUCT_FIELD(u16_t numauthrr);
segundo 0:ac1725ba162c 137 PACK_STRUCT_FIELD(u16_t numextrarr);
segundo 0:ac1725ba162c 138 } PACK_STRUCT_STRUCT;
segundo 0:ac1725ba162c 139 PACK_STRUCT_END
segundo 0:ac1725ba162c 140 #ifdef PACK_STRUCT_USE_INCLUDES
segundo 0:ac1725ba162c 141 # include "arch/epstruct.h"
segundo 0:ac1725ba162c 142 #endif
segundo 0:ac1725ba162c 143 #define SIZEOF_DNS_HDR 12
segundo 0:ac1725ba162c 144
segundo 0:ac1725ba162c 145 /** DNS query message structure.
segundo 0:ac1725ba162c 146 No packing needed: only used locally on the stack. */
segundo 0:ac1725ba162c 147 struct dns_query {
segundo 0:ac1725ba162c 148 /* DNS query record starts with either a domain name or a pointer
segundo 0:ac1725ba162c 149 to a name already present somewhere in the packet. */
segundo 0:ac1725ba162c 150 u16_t type;
segundo 0:ac1725ba162c 151 u16_t cls;
segundo 0:ac1725ba162c 152 };
segundo 0:ac1725ba162c 153 #define SIZEOF_DNS_QUERY 4
segundo 0:ac1725ba162c 154
segundo 0:ac1725ba162c 155 /** DNS answer message structure.
segundo 0:ac1725ba162c 156 No packing needed: only used locally on the stack. */
segundo 0:ac1725ba162c 157 struct dns_answer {
segundo 0:ac1725ba162c 158 /* DNS answer record starts with either a domain name or a pointer
segundo 0:ac1725ba162c 159 to a name already present somewhere in the packet. */
segundo 0:ac1725ba162c 160 u16_t type;
segundo 0:ac1725ba162c 161 u16_t cls;
segundo 0:ac1725ba162c 162 u32_t ttl;
segundo 0:ac1725ba162c 163 u16_t len;
segundo 0:ac1725ba162c 164 };
segundo 0:ac1725ba162c 165 #define SIZEOF_DNS_ANSWER 10
segundo 0:ac1725ba162c 166
segundo 0:ac1725ba162c 167 /** DNS table entry */
segundo 0:ac1725ba162c 168 struct dns_table_entry {
segundo 0:ac1725ba162c 169 u8_t state;
segundo 0:ac1725ba162c 170 u8_t numdns;
segundo 0:ac1725ba162c 171 u8_t tmr;
segundo 0:ac1725ba162c 172 u8_t retries;
segundo 0:ac1725ba162c 173 u8_t seqno;
segundo 0:ac1725ba162c 174 u8_t err;
segundo 0:ac1725ba162c 175 u32_t ttl;
segundo 0:ac1725ba162c 176 char name[DNS_MAX_NAME_LENGTH];
segundo 0:ac1725ba162c 177 ip_addr_t ipaddr;
segundo 0:ac1725ba162c 178 /* pointer to callback on DNS query done */
segundo 0:ac1725ba162c 179 dns_found_callback found;
segundo 0:ac1725ba162c 180 void *arg;
segundo 0:ac1725ba162c 181 };
segundo 0:ac1725ba162c 182
segundo 0:ac1725ba162c 183 #if DNS_LOCAL_HOSTLIST
segundo 0:ac1725ba162c 184
segundo 0:ac1725ba162c 185 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
segundo 0:ac1725ba162c 186 /** Local host-list. For hostnames in this list, no
segundo 0:ac1725ba162c 187 * external name resolution is performed */
segundo 0:ac1725ba162c 188 static struct local_hostlist_entry *local_hostlist_dynamic;
segundo 0:ac1725ba162c 189 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
segundo 0:ac1725ba162c 190
segundo 0:ac1725ba162c 191 /** Defining this allows the local_hostlist_static to be placed in a different
segundo 0:ac1725ba162c 192 * linker section (e.g. FLASH) */
segundo 0:ac1725ba162c 193 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
segundo 0:ac1725ba162c 194 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
segundo 0:ac1725ba162c 195 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
segundo 0:ac1725ba162c 196 /** Defining this allows the local_hostlist_static to be placed in a different
segundo 0:ac1725ba162c 197 * linker section (e.g. FLASH) */
segundo 0:ac1725ba162c 198 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
segundo 0:ac1725ba162c 199 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
segundo 0:ac1725ba162c 200 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
segundo 0:ac1725ba162c 201 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
segundo 0:ac1725ba162c 202 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
segundo 0:ac1725ba162c 203
segundo 0:ac1725ba162c 204 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
segundo 0:ac1725ba162c 205
segundo 0:ac1725ba162c 206 static void dns_init_local();
segundo 0:ac1725ba162c 207 #endif /* DNS_LOCAL_HOSTLIST */
segundo 0:ac1725ba162c 208
segundo 0:ac1725ba162c 209
segundo 0:ac1725ba162c 210 /* forward declarations */
segundo 0:ac1725ba162c 211 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
segundo 0:ac1725ba162c 212 static void dns_check_entries(void);
segundo 0:ac1725ba162c 213
segundo 0:ac1725ba162c 214 /*-----------------------------------------------------------------------------
segundo 0:ac1725ba162c 215 * Globales
segundo 0:ac1725ba162c 216 *----------------------------------------------------------------------------*/
segundo 0:ac1725ba162c 217
segundo 0:ac1725ba162c 218 /* DNS variables */
segundo 0:ac1725ba162c 219 static struct udp_pcb *dns_pcb;
segundo 0:ac1725ba162c 220 static u8_t dns_seqno;
segundo 0:ac1725ba162c 221 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
segundo 0:ac1725ba162c 222 static ip_addr_t dns_servers[DNS_MAX_SERVERS];
segundo 0:ac1725ba162c 223 /** Contiguous buffer for processing responses */
segundo 0:ac1725ba162c 224 static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
segundo 0:ac1725ba162c 225 static u8_t* dns_payload;
segundo 0:ac1725ba162c 226
segundo 0:ac1725ba162c 227 /**
segundo 0:ac1725ba162c 228 * Initialize the resolver: set up the UDP pcb and configure the default server
segundo 0:ac1725ba162c 229 * (DNS_SERVER_ADDRESS).
segundo 0:ac1725ba162c 230 */
segundo 0:ac1725ba162c 231 void
segundo 0:ac1725ba162c 232 dns_init()
segundo 0:ac1725ba162c 233 {
segundo 0:ac1725ba162c 234 ip_addr_t dnsserver;
segundo 0:ac1725ba162c 235
segundo 0:ac1725ba162c 236 dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
segundo 0:ac1725ba162c 237
segundo 0:ac1725ba162c 238 /* initialize default DNS server address */
segundo 0:ac1725ba162c 239 DNS_SERVER_ADDRESS(&dnsserver);
segundo 0:ac1725ba162c 240
segundo 0:ac1725ba162c 241 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
segundo 0:ac1725ba162c 242
segundo 0:ac1725ba162c 243 /* if dns client not yet initialized... */
segundo 0:ac1725ba162c 244 if (dns_pcb == NULL) {
segundo 0:ac1725ba162c 245 dns_pcb = udp_new();
segundo 0:ac1725ba162c 246
segundo 0:ac1725ba162c 247 if (dns_pcb != NULL) {
segundo 0:ac1725ba162c 248 /* initialize DNS table not needed (initialized to zero since it is a
segundo 0:ac1725ba162c 249 * global variable) */
segundo 0:ac1725ba162c 250 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
segundo 0:ac1725ba162c 251 DNS_STATE_UNUSED == 0);
segundo 0:ac1725ba162c 252
segundo 0:ac1725ba162c 253 /* initialize DNS client */
segundo 0:ac1725ba162c 254 udp_bind(dns_pcb, IP_ADDR_ANY, 0);
segundo 0:ac1725ba162c 255 udp_recv(dns_pcb, dns_recv, NULL);
segundo 0:ac1725ba162c 256
segundo 0:ac1725ba162c 257 /* initialize default DNS primary server */
segundo 0:ac1725ba162c 258 dns_setserver(0, &dnsserver);
segundo 0:ac1725ba162c 259 }
segundo 0:ac1725ba162c 260 }
segundo 0:ac1725ba162c 261 #if DNS_LOCAL_HOSTLIST
segundo 0:ac1725ba162c 262 dns_init_local();
segundo 0:ac1725ba162c 263 #endif
segundo 0:ac1725ba162c 264 }
segundo 0:ac1725ba162c 265
segundo 0:ac1725ba162c 266 /**
segundo 0:ac1725ba162c 267 * Initialize one of the DNS servers.
segundo 0:ac1725ba162c 268 *
segundo 0:ac1725ba162c 269 * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
segundo 0:ac1725ba162c 270 * @param dnsserver IP address of the DNS server to set
segundo 0:ac1725ba162c 271 */
segundo 0:ac1725ba162c 272 void
segundo 0:ac1725ba162c 273 dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
segundo 0:ac1725ba162c 274 {
segundo 0:ac1725ba162c 275 if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
segundo 0:ac1725ba162c 276 (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
segundo 0:ac1725ba162c 277 dns_servers[numdns] = (*dnsserver);
segundo 0:ac1725ba162c 278 }
segundo 0:ac1725ba162c 279 }
segundo 0:ac1725ba162c 280
segundo 0:ac1725ba162c 281 /**
segundo 0:ac1725ba162c 282 * Obtain one of the currently configured DNS server.
segundo 0:ac1725ba162c 283 *
segundo 0:ac1725ba162c 284 * @param numdns the index of the DNS server
segundo 0:ac1725ba162c 285 * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
segundo 0:ac1725ba162c 286 * server has not been configured.
segundo 0:ac1725ba162c 287 */
segundo 0:ac1725ba162c 288 ip_addr_t
segundo 0:ac1725ba162c 289 dns_getserver(u8_t numdns)
segundo 0:ac1725ba162c 290 {
segundo 0:ac1725ba162c 291 if (numdns < DNS_MAX_SERVERS) {
segundo 0:ac1725ba162c 292 return dns_servers[numdns];
segundo 0:ac1725ba162c 293 } else {
segundo 0:ac1725ba162c 294 return *IP_ADDR_ANY;
segundo 0:ac1725ba162c 295 }
segundo 0:ac1725ba162c 296 }
segundo 0:ac1725ba162c 297
segundo 0:ac1725ba162c 298 /**
segundo 0:ac1725ba162c 299 * The DNS resolver client timer - handle retries and timeouts and should
segundo 0:ac1725ba162c 300 * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
segundo 0:ac1725ba162c 301 */
segundo 0:ac1725ba162c 302 void
segundo 0:ac1725ba162c 303 dns_tmr(void)
segundo 0:ac1725ba162c 304 {
segundo 0:ac1725ba162c 305 if (dns_pcb != NULL) {
segundo 0:ac1725ba162c 306 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
segundo 0:ac1725ba162c 307 dns_check_entries();
segundo 0:ac1725ba162c 308 }
segundo 0:ac1725ba162c 309 }
segundo 0:ac1725ba162c 310
segundo 0:ac1725ba162c 311 #if DNS_LOCAL_HOSTLIST
segundo 0:ac1725ba162c 312 static void
segundo 0:ac1725ba162c 313 dns_init_local()
segundo 0:ac1725ba162c 314 {
segundo 0:ac1725ba162c 315 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
segundo 0:ac1725ba162c 316 int i;
segundo 0:ac1725ba162c 317 struct local_hostlist_entry *entry;
segundo 0:ac1725ba162c 318 /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
segundo 0:ac1725ba162c 319 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
segundo 0:ac1725ba162c 320 size_t namelen;
segundo 0:ac1725ba162c 321 for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
segundo 0:ac1725ba162c 322 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
segundo 0:ac1725ba162c 323 LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
segundo 0:ac1725ba162c 324 namelen = strlen(init_entry->name);
segundo 0:ac1725ba162c 325 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
segundo 0:ac1725ba162c 326 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
segundo 0:ac1725ba162c 327 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
segundo 0:ac1725ba162c 328 if (entry != NULL) {
segundo 0:ac1725ba162c 329 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
segundo 0:ac1725ba162c 330 MEMCPY((char*)entry->name, init_entry->name, namelen);
segundo 0:ac1725ba162c 331 ((char*)entry->name)[namelen] = 0;
segundo 0:ac1725ba162c 332 entry->addr = init_entry->addr;
segundo 0:ac1725ba162c 333 entry->next = local_hostlist_dynamic;
segundo 0:ac1725ba162c 334 local_hostlist_dynamic = entry;
segundo 0:ac1725ba162c 335 }
segundo 0:ac1725ba162c 336 }
segundo 0:ac1725ba162c 337 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
segundo 0:ac1725ba162c 338 }
segundo 0:ac1725ba162c 339
segundo 0:ac1725ba162c 340 /**
segundo 0:ac1725ba162c 341 * Scans the local host-list for a hostname.
segundo 0:ac1725ba162c 342 *
segundo 0:ac1725ba162c 343 * @param hostname Hostname to look for in the local host-list
segundo 0:ac1725ba162c 344 * @return The first IP address for the hostname in the local host-list or
segundo 0:ac1725ba162c 345 * IPADDR_NONE if not found.
segundo 0:ac1725ba162c 346 */
segundo 0:ac1725ba162c 347 static u32_t
segundo 0:ac1725ba162c 348 dns_lookup_local(const char *hostname)
segundo 0:ac1725ba162c 349 {
segundo 0:ac1725ba162c 350 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
segundo 0:ac1725ba162c 351 struct local_hostlist_entry *entry = local_hostlist_dynamic;
segundo 0:ac1725ba162c 352 while(entry != NULL) {
segundo 0:ac1725ba162c 353 if(strcmp(entry->name, hostname) == 0) {
segundo 0:ac1725ba162c 354 return ip4_addr_get_u32(&entry->addr);
segundo 0:ac1725ba162c 355 }
segundo 0:ac1725ba162c 356 entry = entry->next;
segundo 0:ac1725ba162c 357 }
segundo 0:ac1725ba162c 358 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
segundo 0:ac1725ba162c 359 int i;
segundo 0:ac1725ba162c 360 for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
segundo 0:ac1725ba162c 361 if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
segundo 0:ac1725ba162c 362 return ip4_addr_get_u32(&local_hostlist_static[i].addr);
segundo 0:ac1725ba162c 363 }
segundo 0:ac1725ba162c 364 }
segundo 0:ac1725ba162c 365 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
segundo 0:ac1725ba162c 366 return IPADDR_NONE;
segundo 0:ac1725ba162c 367 }
segundo 0:ac1725ba162c 368
segundo 0:ac1725ba162c 369 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
segundo 0:ac1725ba162c 370 /** Remove all entries from the local host-list for a specific hostname
segundo 0:ac1725ba162c 371 * and/or IP addess
segundo 0:ac1725ba162c 372 *
segundo 0:ac1725ba162c 373 * @param hostname hostname for which entries shall be removed from the local
segundo 0:ac1725ba162c 374 * host-list
segundo 0:ac1725ba162c 375 * @param addr address for which entries shall be removed from the local host-list
segundo 0:ac1725ba162c 376 * @return the number of removed entries
segundo 0:ac1725ba162c 377 */
segundo 0:ac1725ba162c 378 int
segundo 0:ac1725ba162c 379 dns_local_removehost(const char *hostname, const ip_addr_t *addr)
segundo 0:ac1725ba162c 380 {
segundo 0:ac1725ba162c 381 int removed = 0;
segundo 0:ac1725ba162c 382 struct local_hostlist_entry *entry = local_hostlist_dynamic;
segundo 0:ac1725ba162c 383 struct local_hostlist_entry *last_entry = NULL;
segundo 0:ac1725ba162c 384 while (entry != NULL) {
segundo 0:ac1725ba162c 385 if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
segundo 0:ac1725ba162c 386 ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
segundo 0:ac1725ba162c 387 struct local_hostlist_entry *free_entry;
segundo 0:ac1725ba162c 388 if (last_entry != NULL) {
segundo 0:ac1725ba162c 389 last_entry->next = entry->next;
segundo 0:ac1725ba162c 390 } else {
segundo 0:ac1725ba162c 391 local_hostlist_dynamic = entry->next;
segundo 0:ac1725ba162c 392 }
segundo 0:ac1725ba162c 393 free_entry = entry;
segundo 0:ac1725ba162c 394 entry = entry->next;
segundo 0:ac1725ba162c 395 memp_free(MEMP_LOCALHOSTLIST, free_entry);
segundo 0:ac1725ba162c 396 removed++;
segundo 0:ac1725ba162c 397 } else {
segundo 0:ac1725ba162c 398 last_entry = entry;
segundo 0:ac1725ba162c 399 entry = entry->next;
segundo 0:ac1725ba162c 400 }
segundo 0:ac1725ba162c 401 }
segundo 0:ac1725ba162c 402 return removed;
segundo 0:ac1725ba162c 403 }
segundo 0:ac1725ba162c 404
segundo 0:ac1725ba162c 405 /**
segundo 0:ac1725ba162c 406 * Add a hostname/IP address pair to the local host-list.
segundo 0:ac1725ba162c 407 * Duplicates are not checked.
segundo 0:ac1725ba162c 408 *
segundo 0:ac1725ba162c 409 * @param hostname hostname of the new entry
segundo 0:ac1725ba162c 410 * @param addr IP address of the new entry
segundo 0:ac1725ba162c 411 * @return ERR_OK if succeeded or ERR_MEM on memory error
segundo 0:ac1725ba162c 412 */
segundo 0:ac1725ba162c 413 err_t
segundo 0:ac1725ba162c 414 dns_local_addhost(const char *hostname, const ip_addr_t *addr)
segundo 0:ac1725ba162c 415 {
segundo 0:ac1725ba162c 416 struct local_hostlist_entry *entry;
segundo 0:ac1725ba162c 417 size_t namelen;
segundo 0:ac1725ba162c 418 LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
segundo 0:ac1725ba162c 419 namelen = strlen(hostname);
segundo 0:ac1725ba162c 420 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
segundo 0:ac1725ba162c 421 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
segundo 0:ac1725ba162c 422 if (entry == NULL) {
segundo 0:ac1725ba162c 423 return ERR_MEM;
segundo 0:ac1725ba162c 424 }
segundo 0:ac1725ba162c 425 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
segundo 0:ac1725ba162c 426 MEMCPY((char*)entry->name, hostname, namelen);
segundo 0:ac1725ba162c 427 ((char*)entry->name)[namelen] = 0;
segundo 0:ac1725ba162c 428 ip_addr_copy(entry->addr, *addr);
segundo 0:ac1725ba162c 429 entry->next = local_hostlist_dynamic;
segundo 0:ac1725ba162c 430 local_hostlist_dynamic = entry;
segundo 0:ac1725ba162c 431 return ERR_OK;
segundo 0:ac1725ba162c 432 }
segundo 0:ac1725ba162c 433 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
segundo 0:ac1725ba162c 434 #endif /* DNS_LOCAL_HOSTLIST */
segundo 0:ac1725ba162c 435
segundo 0:ac1725ba162c 436 /**
segundo 0:ac1725ba162c 437 * Look up a hostname in the array of known hostnames.
segundo 0:ac1725ba162c 438 *
segundo 0:ac1725ba162c 439 * @note This function only looks in the internal array of known
segundo 0:ac1725ba162c 440 * hostnames, it does not send out a query for the hostname if none
segundo 0:ac1725ba162c 441 * was found. The function dns_enqueue() can be used to send a query
segundo 0:ac1725ba162c 442 * for a hostname.
segundo 0:ac1725ba162c 443 *
segundo 0:ac1725ba162c 444 * @param name the hostname to look up
segundo 0:ac1725ba162c 445 * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
segundo 0:ac1725ba162c 446 * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
segundo 0:ac1725ba162c 447 * was not found in the cached dns_table.
segundo 0:ac1725ba162c 448 */
segundo 0:ac1725ba162c 449 static u32_t
segundo 0:ac1725ba162c 450 dns_lookup(const char *name)
segundo 0:ac1725ba162c 451 {
segundo 0:ac1725ba162c 452 u8_t i;
segundo 0:ac1725ba162c 453 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
segundo 0:ac1725ba162c 454 u32_t addr;
segundo 0:ac1725ba162c 455 #endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
segundo 0:ac1725ba162c 456 #if DNS_LOCAL_HOSTLIST
segundo 0:ac1725ba162c 457 if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
segundo 0:ac1725ba162c 458 return addr;
segundo 0:ac1725ba162c 459 }
segundo 0:ac1725ba162c 460 #endif /* DNS_LOCAL_HOSTLIST */
segundo 0:ac1725ba162c 461 #ifdef DNS_LOOKUP_LOCAL_EXTERN
segundo 0:ac1725ba162c 462 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
segundo 0:ac1725ba162c 463 return addr;
segundo 0:ac1725ba162c 464 }
segundo 0:ac1725ba162c 465 #endif /* DNS_LOOKUP_LOCAL_EXTERN */
segundo 0:ac1725ba162c 466
segundo 0:ac1725ba162c 467 /* Walk through name list, return entry if found. If not, return NULL. */
segundo 0:ac1725ba162c 468 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
segundo 0:ac1725ba162c 469 if ((dns_table[i].state == DNS_STATE_DONE) &&
segundo 0:ac1725ba162c 470 (strcmp(name, dns_table[i].name) == 0)) {
segundo 0:ac1725ba162c 471 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
segundo 0:ac1725ba162c 472 ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
segundo 0:ac1725ba162c 473 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
segundo 0:ac1725ba162c 474 return ip4_addr_get_u32(&dns_table[i].ipaddr);
segundo 0:ac1725ba162c 475 }
segundo 0:ac1725ba162c 476 }
segundo 0:ac1725ba162c 477
segundo 0:ac1725ba162c 478 return IPADDR_NONE;
segundo 0:ac1725ba162c 479 }
segundo 0:ac1725ba162c 480
segundo 0:ac1725ba162c 481 #if DNS_DOES_NAME_CHECK
segundo 0:ac1725ba162c 482 /**
segundo 0:ac1725ba162c 483 * Compare the "dotted" name "query" with the encoded name "response"
segundo 0:ac1725ba162c 484 * to make sure an answer from the DNS server matches the current dns_table
segundo 0:ac1725ba162c 485 * entry (otherwise, answers might arrive late for hostname not on the list
segundo 0:ac1725ba162c 486 * any more).
segundo 0:ac1725ba162c 487 *
segundo 0:ac1725ba162c 488 * @param query hostname (not encoded) from the dns_table
segundo 0:ac1725ba162c 489 * @param response encoded hostname in the DNS response
segundo 0:ac1725ba162c 490 * @return 0: names equal; 1: names differ
segundo 0:ac1725ba162c 491 */
segundo 0:ac1725ba162c 492 static u8_t
segundo 0:ac1725ba162c 493 dns_compare_name(unsigned char *query, unsigned char *response)
segundo 0:ac1725ba162c 494 {
segundo 0:ac1725ba162c 495 unsigned char n;
segundo 0:ac1725ba162c 496
segundo 0:ac1725ba162c 497 do {
segundo 0:ac1725ba162c 498 n = *response++;
segundo 0:ac1725ba162c 499 /** @see RFC 1035 - 4.1.4. Message compression */
segundo 0:ac1725ba162c 500 if ((n & 0xc0) == 0xc0) {
segundo 0:ac1725ba162c 501 /* Compressed name */
segundo 0:ac1725ba162c 502 break;
segundo 0:ac1725ba162c 503 } else {
segundo 0:ac1725ba162c 504 /* Not compressed name */
segundo 0:ac1725ba162c 505 while (n > 0) {
segundo 0:ac1725ba162c 506 if ((*query) != (*response)) {
segundo 0:ac1725ba162c 507 return 1;
segundo 0:ac1725ba162c 508 }
segundo 0:ac1725ba162c 509 ++response;
segundo 0:ac1725ba162c 510 ++query;
segundo 0:ac1725ba162c 511 --n;
segundo 0:ac1725ba162c 512 };
segundo 0:ac1725ba162c 513 ++query;
segundo 0:ac1725ba162c 514 }
segundo 0:ac1725ba162c 515 } while (*response != 0);
segundo 0:ac1725ba162c 516
segundo 0:ac1725ba162c 517 return 0;
segundo 0:ac1725ba162c 518 }
segundo 0:ac1725ba162c 519 #endif /* DNS_DOES_NAME_CHECK */
segundo 0:ac1725ba162c 520
segundo 0:ac1725ba162c 521 /**
segundo 0:ac1725ba162c 522 * Walk through a compact encoded DNS name and return the end of the name.
segundo 0:ac1725ba162c 523 *
segundo 0:ac1725ba162c 524 * @param query encoded DNS name in the DNS server response
segundo 0:ac1725ba162c 525 * @return end of the name
segundo 0:ac1725ba162c 526 */
segundo 0:ac1725ba162c 527 static unsigned char *
segundo 0:ac1725ba162c 528 dns_parse_name(unsigned char *query)
segundo 0:ac1725ba162c 529 {
segundo 0:ac1725ba162c 530 unsigned char n;
segundo 0:ac1725ba162c 531
segundo 0:ac1725ba162c 532 do {
segundo 0:ac1725ba162c 533 n = *query++;
segundo 0:ac1725ba162c 534 /** @see RFC 1035 - 4.1.4. Message compression */
segundo 0:ac1725ba162c 535 if ((n & 0xc0) == 0xc0) {
segundo 0:ac1725ba162c 536 /* Compressed name */
segundo 0:ac1725ba162c 537 break;
segundo 0:ac1725ba162c 538 } else {
segundo 0:ac1725ba162c 539 /* Not compressed name */
segundo 0:ac1725ba162c 540 while (n > 0) {
segundo 0:ac1725ba162c 541 ++query;
segundo 0:ac1725ba162c 542 --n;
segundo 0:ac1725ba162c 543 };
segundo 0:ac1725ba162c 544 }
segundo 0:ac1725ba162c 545 } while (*query != 0);
segundo 0:ac1725ba162c 546
segundo 0:ac1725ba162c 547 return query + 1;
segundo 0:ac1725ba162c 548 }
segundo 0:ac1725ba162c 549
segundo 0:ac1725ba162c 550 /**
segundo 0:ac1725ba162c 551 * Send a DNS query packet.
segundo 0:ac1725ba162c 552 *
segundo 0:ac1725ba162c 553 * @param numdns index of the DNS server in the dns_servers table
segundo 0:ac1725ba162c 554 * @param name hostname to query
segundo 0:ac1725ba162c 555 * @param id index of the hostname in dns_table, used as transaction ID in the
segundo 0:ac1725ba162c 556 * DNS query packet
segundo 0:ac1725ba162c 557 * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
segundo 0:ac1725ba162c 558 */
segundo 0:ac1725ba162c 559 static err_t
segundo 0:ac1725ba162c 560 dns_send(u8_t numdns, const char* name, u8_t id)
segundo 0:ac1725ba162c 561 {
segundo 0:ac1725ba162c 562 err_t err;
segundo 0:ac1725ba162c 563 struct dns_hdr *hdr;
segundo 0:ac1725ba162c 564 struct dns_query qry;
segundo 0:ac1725ba162c 565 struct pbuf *p;
segundo 0:ac1725ba162c 566 char *query, *nptr;
segundo 0:ac1725ba162c 567 const char *pHostname;
segundo 0:ac1725ba162c 568 u8_t n;
segundo 0:ac1725ba162c 569
segundo 0:ac1725ba162c 570 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
segundo 0:ac1725ba162c 571 (u16_t)(numdns), name));
segundo 0:ac1725ba162c 572 LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
segundo 0:ac1725ba162c 573 LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
segundo 0:ac1725ba162c 574
segundo 0:ac1725ba162c 575 /* if here, we have either a new query or a retry on a previous query to process */
segundo 0:ac1725ba162c 576 p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
segundo 0:ac1725ba162c 577 SIZEOF_DNS_QUERY, PBUF_RAM);
segundo 0:ac1725ba162c 578 if (p != NULL) {
segundo 0:ac1725ba162c 579 LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
segundo 0:ac1725ba162c 580 /* fill dns header */
segundo 0:ac1725ba162c 581 hdr = (struct dns_hdr*)p->payload;
segundo 0:ac1725ba162c 582 memset(hdr, 0, SIZEOF_DNS_HDR);
segundo 0:ac1725ba162c 583 hdr->id = htons(id);
segundo 0:ac1725ba162c 584 hdr->flags1 = DNS_FLAG1_RD;
segundo 0:ac1725ba162c 585 hdr->numquestions = PP_HTONS(1);
segundo 0:ac1725ba162c 586 query = (char*)hdr + SIZEOF_DNS_HDR;
segundo 0:ac1725ba162c 587 pHostname = name;
segundo 0:ac1725ba162c 588 --pHostname;
segundo 0:ac1725ba162c 589
segundo 0:ac1725ba162c 590 /* convert hostname into suitable query format. */
segundo 0:ac1725ba162c 591 do {
segundo 0:ac1725ba162c 592 ++pHostname;
segundo 0:ac1725ba162c 593 nptr = query;
segundo 0:ac1725ba162c 594 ++query;
segundo 0:ac1725ba162c 595 for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
segundo 0:ac1725ba162c 596 *query = *pHostname;
segundo 0:ac1725ba162c 597 ++query;
segundo 0:ac1725ba162c 598 ++n;
segundo 0:ac1725ba162c 599 }
segundo 0:ac1725ba162c 600 *nptr = n;
segundo 0:ac1725ba162c 601 } while(*pHostname != 0);
segundo 0:ac1725ba162c 602 *query++='\0';
segundo 0:ac1725ba162c 603
segundo 0:ac1725ba162c 604 /* fill dns query */
segundo 0:ac1725ba162c 605 qry.type = PP_HTONS(DNS_RRTYPE_A);
segundo 0:ac1725ba162c 606 qry.cls = PP_HTONS(DNS_RRCLASS_IN);
segundo 0:ac1725ba162c 607 SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
segundo 0:ac1725ba162c 608
segundo 0:ac1725ba162c 609 /* resize pbuf to the exact dns query */
segundo 0:ac1725ba162c 610 pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
segundo 0:ac1725ba162c 611
segundo 0:ac1725ba162c 612 /* connect to the server for faster receiving */
segundo 0:ac1725ba162c 613 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
segundo 0:ac1725ba162c 614 /* send dns packet */
segundo 0:ac1725ba162c 615 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
segundo 0:ac1725ba162c 616
segundo 0:ac1725ba162c 617 /* free pbuf */
segundo 0:ac1725ba162c 618 pbuf_free(p);
segundo 0:ac1725ba162c 619 } else {
segundo 0:ac1725ba162c 620 err = ERR_MEM;
segundo 0:ac1725ba162c 621 }
segundo 0:ac1725ba162c 622
segundo 0:ac1725ba162c 623 return err;
segundo 0:ac1725ba162c 624 }
segundo 0:ac1725ba162c 625
segundo 0:ac1725ba162c 626 /**
segundo 0:ac1725ba162c 627 * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
segundo 0:ac1725ba162c 628 * Check an entry in the dns_table:
segundo 0:ac1725ba162c 629 * - send out query for new entries
segundo 0:ac1725ba162c 630 * - retry old pending entries on timeout (also with different servers)
segundo 0:ac1725ba162c 631 * - remove completed entries from the table if their TTL has expired
segundo 0:ac1725ba162c 632 *
segundo 0:ac1725ba162c 633 * @param i index of the dns_table entry to check
segundo 0:ac1725ba162c 634 */
segundo 0:ac1725ba162c 635 static void
segundo 0:ac1725ba162c 636 dns_check_entry(u8_t i)
segundo 0:ac1725ba162c 637 {
segundo 0:ac1725ba162c 638 err_t err;
segundo 0:ac1725ba162c 639 struct dns_table_entry *pEntry = &dns_table[i];
segundo 0:ac1725ba162c 640
segundo 0:ac1725ba162c 641 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
segundo 0:ac1725ba162c 642
segundo 0:ac1725ba162c 643 switch(pEntry->state) {
segundo 0:ac1725ba162c 644
segundo 0:ac1725ba162c 645 case DNS_STATE_NEW: {
segundo 0:ac1725ba162c 646 /* initialize new entry */
segundo 0:ac1725ba162c 647 pEntry->state = DNS_STATE_ASKING;
segundo 0:ac1725ba162c 648 pEntry->numdns = 0;
segundo 0:ac1725ba162c 649 pEntry->tmr = 1;
segundo 0:ac1725ba162c 650 pEntry->retries = 0;
segundo 0:ac1725ba162c 651
segundo 0:ac1725ba162c 652 /* send DNS packet for this entry */
segundo 0:ac1725ba162c 653 err = dns_send(pEntry->numdns, pEntry->name, i);
segundo 0:ac1725ba162c 654 if (err != ERR_OK) {
segundo 0:ac1725ba162c 655 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
segundo 0:ac1725ba162c 656 ("dns_send returned error: %d\n", err)); //FIX DG, lwip_strerr is part of lwip/api
segundo 0:ac1725ba162c 657 }
segundo 0:ac1725ba162c 658 break;
segundo 0:ac1725ba162c 659 }
segundo 0:ac1725ba162c 660
segundo 0:ac1725ba162c 661 case DNS_STATE_ASKING: {
segundo 0:ac1725ba162c 662 if (--pEntry->tmr == 0) {
segundo 0:ac1725ba162c 663 if (++pEntry->retries == DNS_MAX_RETRIES) {
segundo 0:ac1725ba162c 664 if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
segundo 0:ac1725ba162c 665 /* change of server */
segundo 0:ac1725ba162c 666 pEntry->numdns++;
segundo 0:ac1725ba162c 667 pEntry->tmr = 1;
segundo 0:ac1725ba162c 668 pEntry->retries = 0;
segundo 0:ac1725ba162c 669 break;
segundo 0:ac1725ba162c 670 } else {
segundo 0:ac1725ba162c 671 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
segundo 0:ac1725ba162c 672 /* call specified callback function if provided */
segundo 0:ac1725ba162c 673 if (pEntry->found)
segundo 0:ac1725ba162c 674 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
segundo 0:ac1725ba162c 675 /* flush this entry */
segundo 0:ac1725ba162c 676 pEntry->state = DNS_STATE_UNUSED;
segundo 0:ac1725ba162c 677 pEntry->found = NULL;
segundo 0:ac1725ba162c 678 break;
segundo 0:ac1725ba162c 679 }
segundo 0:ac1725ba162c 680 }
segundo 0:ac1725ba162c 681
segundo 0:ac1725ba162c 682 /* wait longer for the next retry */
segundo 0:ac1725ba162c 683 pEntry->tmr = pEntry->retries;
segundo 0:ac1725ba162c 684
segundo 0:ac1725ba162c 685 /* send DNS packet for this entry */
segundo 0:ac1725ba162c 686 err = dns_send(pEntry->numdns, pEntry->name, i);
segundo 0:ac1725ba162c 687 if (err != ERR_OK) {
segundo 0:ac1725ba162c 688 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
segundo 0:ac1725ba162c 689 ("dns_send returned error: %d\n", err)); //FIX DG, lwip_strerr is part of lwip/api
segundo 0:ac1725ba162c 690 }
segundo 0:ac1725ba162c 691 }
segundo 0:ac1725ba162c 692 break;
segundo 0:ac1725ba162c 693 }
segundo 0:ac1725ba162c 694
segundo 0:ac1725ba162c 695 case DNS_STATE_DONE: {
segundo 0:ac1725ba162c 696 /* if the time to live is nul */
segundo 0:ac1725ba162c 697 if (--pEntry->ttl == 0) {
segundo 0:ac1725ba162c 698 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
segundo 0:ac1725ba162c 699 /* flush this entry */
segundo 0:ac1725ba162c 700 pEntry->state = DNS_STATE_UNUSED;
segundo 0:ac1725ba162c 701 pEntry->found = NULL;
segundo 0:ac1725ba162c 702 }
segundo 0:ac1725ba162c 703 break;
segundo 0:ac1725ba162c 704 }
segundo 0:ac1725ba162c 705 case DNS_STATE_UNUSED:
segundo 0:ac1725ba162c 706 /* nothing to do */
segundo 0:ac1725ba162c 707 break;
segundo 0:ac1725ba162c 708 default:
segundo 0:ac1725ba162c 709 LWIP_ASSERT("unknown dns_table entry state:", 0);
segundo 0:ac1725ba162c 710 break;
segundo 0:ac1725ba162c 711 }
segundo 0:ac1725ba162c 712 }
segundo 0:ac1725ba162c 713
segundo 0:ac1725ba162c 714 /**
segundo 0:ac1725ba162c 715 * Call dns_check_entry for each entry in dns_table - check all entries.
segundo 0:ac1725ba162c 716 */
segundo 0:ac1725ba162c 717 static void
segundo 0:ac1725ba162c 718 dns_check_entries(void)
segundo 0:ac1725ba162c 719 {
segundo 0:ac1725ba162c 720 u8_t i;
segundo 0:ac1725ba162c 721
segundo 0:ac1725ba162c 722 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
segundo 0:ac1725ba162c 723 dns_check_entry(i);
segundo 0:ac1725ba162c 724 }
segundo 0:ac1725ba162c 725 }
segundo 0:ac1725ba162c 726
segundo 0:ac1725ba162c 727 /**
segundo 0:ac1725ba162c 728 * Receive input function for DNS response packets arriving for the dns UDP pcb.
segundo 0:ac1725ba162c 729 *
segundo 0:ac1725ba162c 730 * @params see udp.h
segundo 0:ac1725ba162c 731 */
segundo 0:ac1725ba162c 732 static void
segundo 0:ac1725ba162c 733 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
segundo 0:ac1725ba162c 734 {
segundo 0:ac1725ba162c 735 u16_t i;
segundo 0:ac1725ba162c 736 char *pHostname;
segundo 0:ac1725ba162c 737 struct dns_hdr *hdr;
segundo 0:ac1725ba162c 738 struct dns_answer ans;
segundo 0:ac1725ba162c 739 struct dns_table_entry *pEntry;
segundo 0:ac1725ba162c 740 u16_t nquestions, nanswers;
segundo 0:ac1725ba162c 741
segundo 0:ac1725ba162c 742 LWIP_UNUSED_ARG(arg);
segundo 0:ac1725ba162c 743 LWIP_UNUSED_ARG(pcb);
segundo 0:ac1725ba162c 744 LWIP_UNUSED_ARG(addr);
segundo 0:ac1725ba162c 745 LWIP_UNUSED_ARG(port);
segundo 0:ac1725ba162c 746
segundo 0:ac1725ba162c 747 /* is the dns message too big ? */
segundo 0:ac1725ba162c 748 if (p->tot_len > DNS_MSG_SIZE) {
segundo 0:ac1725ba162c 749 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
segundo 0:ac1725ba162c 750 /* free pbuf and return */
segundo 0:ac1725ba162c 751 goto memerr;
segundo 0:ac1725ba162c 752 }
segundo 0:ac1725ba162c 753
segundo 0:ac1725ba162c 754 /* is the dns message big enough ? */
segundo 0:ac1725ba162c 755 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
segundo 0:ac1725ba162c 756 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
segundo 0:ac1725ba162c 757 /* free pbuf and return */
segundo 0:ac1725ba162c 758 goto memerr;
segundo 0:ac1725ba162c 759 }
segundo 0:ac1725ba162c 760
segundo 0:ac1725ba162c 761 /* copy dns payload inside static buffer for processing */
segundo 0:ac1725ba162c 762 if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
segundo 0:ac1725ba162c 763 /* The ID in the DNS header should be our entry into the name table. */
segundo 0:ac1725ba162c 764 hdr = (struct dns_hdr*)dns_payload;
segundo 0:ac1725ba162c 765 i = htons(hdr->id);
segundo 0:ac1725ba162c 766 if (i < DNS_TABLE_SIZE) {
segundo 0:ac1725ba162c 767 pEntry = &dns_table[i];
segundo 0:ac1725ba162c 768 if(pEntry->state == DNS_STATE_ASKING) {
segundo 0:ac1725ba162c 769 /* This entry is now completed. */
segundo 0:ac1725ba162c 770 pEntry->state = DNS_STATE_DONE;
segundo 0:ac1725ba162c 771 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
segundo 0:ac1725ba162c 772
segundo 0:ac1725ba162c 773 /* We only care about the question(s) and the answers. The authrr
segundo 0:ac1725ba162c 774 and the extrarr are simply discarded. */
segundo 0:ac1725ba162c 775 nquestions = htons(hdr->numquestions);
segundo 0:ac1725ba162c 776 nanswers = htons(hdr->numanswers);
segundo 0:ac1725ba162c 777
segundo 0:ac1725ba162c 778 /* Check for error. If so, call callback to inform. */
segundo 0:ac1725ba162c 779 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
segundo 0:ac1725ba162c 780 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
segundo 0:ac1725ba162c 781 /* call callback to indicate error, clean up memory and return */
segundo 0:ac1725ba162c 782 goto responseerr;
segundo 0:ac1725ba162c 783 }
segundo 0:ac1725ba162c 784
segundo 0:ac1725ba162c 785 #if DNS_DOES_NAME_CHECK
segundo 0:ac1725ba162c 786 /* Check if the name in the "question" part match with the name in the entry. */
segundo 0:ac1725ba162c 787 if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
segundo 0:ac1725ba162c 788 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
segundo 0:ac1725ba162c 789 /* call callback to indicate error, clean up memory and return */
segundo 0:ac1725ba162c 790 goto responseerr;
segundo 0:ac1725ba162c 791 }
segundo 0:ac1725ba162c 792 #endif /* DNS_DOES_NAME_CHECK */
segundo 0:ac1725ba162c 793
segundo 0:ac1725ba162c 794 /* Skip the name in the "question" part */
segundo 0:ac1725ba162c 795 pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
segundo 0:ac1725ba162c 796
segundo 0:ac1725ba162c 797 while (nanswers > 0) {
segundo 0:ac1725ba162c 798 /* skip answer resource record's host name */
segundo 0:ac1725ba162c 799 pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
segundo 0:ac1725ba162c 800
segundo 0:ac1725ba162c 801 /* Check for IP address type and Internet class. Others are discarded. */
segundo 0:ac1725ba162c 802 SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
segundo 0:ac1725ba162c 803 if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
segundo 0:ac1725ba162c 804 (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
segundo 0:ac1725ba162c 805 /* read the answer resource record's TTL, and maximize it if needed */
segundo 0:ac1725ba162c 806 pEntry->ttl = ntohl(ans.ttl);
segundo 0:ac1725ba162c 807 if (pEntry->ttl > DNS_MAX_TTL) {
segundo 0:ac1725ba162c 808 pEntry->ttl = DNS_MAX_TTL;
segundo 0:ac1725ba162c 809 }
segundo 0:ac1725ba162c 810 /* read the IP address after answer resource record's header */
segundo 0:ac1725ba162c 811 SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
segundo 0:ac1725ba162c 812 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
segundo 0:ac1725ba162c 813 ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
segundo 0:ac1725ba162c 814 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
segundo 0:ac1725ba162c 815 /* call specified callback function if provided */
segundo 0:ac1725ba162c 816 if (pEntry->found) {
segundo 0:ac1725ba162c 817 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
segundo 0:ac1725ba162c 818 }
segundo 0:ac1725ba162c 819 /* deallocate memory and return */
segundo 0:ac1725ba162c 820 goto memerr;
segundo 0:ac1725ba162c 821 } else {
segundo 0:ac1725ba162c 822 pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
segundo 0:ac1725ba162c 823 }
segundo 0:ac1725ba162c 824 --nanswers;
segundo 0:ac1725ba162c 825 }
segundo 0:ac1725ba162c 826 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
segundo 0:ac1725ba162c 827 /* call callback to indicate error, clean up memory and return */
segundo 0:ac1725ba162c 828 goto responseerr;
segundo 0:ac1725ba162c 829 }
segundo 0:ac1725ba162c 830 }
segundo 0:ac1725ba162c 831 }
segundo 0:ac1725ba162c 832
segundo 0:ac1725ba162c 833 /* deallocate memory and return */
segundo 0:ac1725ba162c 834 goto memerr;
segundo 0:ac1725ba162c 835
segundo 0:ac1725ba162c 836 responseerr:
segundo 0:ac1725ba162c 837 /* ERROR: call specified callback function with NULL as name to indicate an error */
segundo 0:ac1725ba162c 838 if (pEntry->found) {
segundo 0:ac1725ba162c 839 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
segundo 0:ac1725ba162c 840 }
segundo 0:ac1725ba162c 841 /* flush this entry */
segundo 0:ac1725ba162c 842 pEntry->state = DNS_STATE_UNUSED;
segundo 0:ac1725ba162c 843 pEntry->found = NULL;
segundo 0:ac1725ba162c 844
segundo 0:ac1725ba162c 845 memerr:
segundo 0:ac1725ba162c 846 /* free pbuf */
segundo 0:ac1725ba162c 847 pbuf_free(p);
segundo 0:ac1725ba162c 848 return;
segundo 0:ac1725ba162c 849 }
segundo 0:ac1725ba162c 850
segundo 0:ac1725ba162c 851 /**
segundo 0:ac1725ba162c 852 * Queues a new hostname to resolve and sends out a DNS query for that hostname
segundo 0:ac1725ba162c 853 *
segundo 0:ac1725ba162c 854 * @param name the hostname that is to be queried
segundo 0:ac1725ba162c 855 * @param found a callback founction to be called on success, failure or timeout
segundo 0:ac1725ba162c 856 * @param callback_arg argument to pass to the callback function
segundo 0:ac1725ba162c 857 * @return @return a err_t return code.
segundo 0:ac1725ba162c 858 */
segundo 0:ac1725ba162c 859 static err_t
segundo 0:ac1725ba162c 860 dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
segundo 0:ac1725ba162c 861 {
segundo 0:ac1725ba162c 862 u8_t i;
segundo 0:ac1725ba162c 863 u8_t lseq, lseqi;
segundo 0:ac1725ba162c 864 struct dns_table_entry *pEntry = NULL;
segundo 0:ac1725ba162c 865 size_t namelen;
segundo 0:ac1725ba162c 866
segundo 0:ac1725ba162c 867 /* search an unused entry, or the oldest one */
segundo 0:ac1725ba162c 868 lseq = lseqi = 0;
segundo 0:ac1725ba162c 869 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
segundo 0:ac1725ba162c 870 pEntry = &dns_table[i];
segundo 0:ac1725ba162c 871 /* is it an unused entry ? */
segundo 0:ac1725ba162c 872 if (pEntry->state == DNS_STATE_UNUSED)
segundo 0:ac1725ba162c 873 break;
segundo 0:ac1725ba162c 874
segundo 0:ac1725ba162c 875 /* check if this is the oldest completed entry */
segundo 0:ac1725ba162c 876 if (pEntry->state == DNS_STATE_DONE) {
segundo 0:ac1725ba162c 877 if ((dns_seqno - pEntry->seqno) > lseq) {
segundo 0:ac1725ba162c 878 lseq = dns_seqno - pEntry->seqno;
segundo 0:ac1725ba162c 879 lseqi = i;
segundo 0:ac1725ba162c 880 }
segundo 0:ac1725ba162c 881 }
segundo 0:ac1725ba162c 882 }
segundo 0:ac1725ba162c 883
segundo 0:ac1725ba162c 884 /* if we don't have found an unused entry, use the oldest completed one */
segundo 0:ac1725ba162c 885 if (i == DNS_TABLE_SIZE) {
segundo 0:ac1725ba162c 886 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
segundo 0:ac1725ba162c 887 /* no entry can't be used now, table is full */
segundo 0:ac1725ba162c 888 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
segundo 0:ac1725ba162c 889 return ERR_MEM;
segundo 0:ac1725ba162c 890 } else {
segundo 0:ac1725ba162c 891 /* use the oldest completed one */
segundo 0:ac1725ba162c 892 i = lseqi;
segundo 0:ac1725ba162c 893 pEntry = &dns_table[i];
segundo 0:ac1725ba162c 894 }
segundo 0:ac1725ba162c 895 }
segundo 0:ac1725ba162c 896
segundo 0:ac1725ba162c 897 /* use this entry */
segundo 0:ac1725ba162c 898 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
segundo 0:ac1725ba162c 899
segundo 0:ac1725ba162c 900 /* fill the entry */
segundo 0:ac1725ba162c 901 pEntry->state = DNS_STATE_NEW;
segundo 0:ac1725ba162c 902 pEntry->seqno = dns_seqno++;
segundo 0:ac1725ba162c 903 pEntry->found = found;
segundo 0:ac1725ba162c 904 pEntry->arg = callback_arg;
segundo 0:ac1725ba162c 905 namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
segundo 0:ac1725ba162c 906 MEMCPY(pEntry->name, name, namelen);
segundo 0:ac1725ba162c 907 pEntry->name[namelen] = 0;
segundo 0:ac1725ba162c 908
segundo 0:ac1725ba162c 909 /* force to send query without waiting timer */
segundo 0:ac1725ba162c 910 dns_check_entry(i);
segundo 0:ac1725ba162c 911
segundo 0:ac1725ba162c 912 /* dns query is enqueued */
segundo 0:ac1725ba162c 913 return ERR_INPROGRESS;
segundo 0:ac1725ba162c 914 }
segundo 0:ac1725ba162c 915
segundo 0:ac1725ba162c 916 /**
segundo 0:ac1725ba162c 917 * Resolve a hostname (string) into an IP address.
segundo 0:ac1725ba162c 918 * NON-BLOCKING callback version for use with raw API!!!
segundo 0:ac1725ba162c 919 *
segundo 0:ac1725ba162c 920 * Returns immediately with one of err_t return codes:
segundo 0:ac1725ba162c 921 * - ERR_OK if hostname is a valid IP address string or the host
segundo 0:ac1725ba162c 922 * name is already in the local names table.
segundo 0:ac1725ba162c 923 * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
segundo 0:ac1725ba162c 924 * for resolution if no errors are present.
segundo 0:ac1725ba162c 925 *
segundo 0:ac1725ba162c 926 * @param hostname the hostname that is to be queried
segundo 0:ac1725ba162c 927 * @param addr pointer to a ip_addr_t where to store the address if it is already
segundo 0:ac1725ba162c 928 * cached in the dns_table (only valid if ERR_OK is returned!)
segundo 0:ac1725ba162c 929 * @param found a callback function to be called on success, failure or timeout (only if
segundo 0:ac1725ba162c 930 * ERR_INPROGRESS is returned!)
segundo 0:ac1725ba162c 931 * @param callback_arg argument to pass to the callback function
segundo 0:ac1725ba162c 932 * @return a err_t return code.
segundo 0:ac1725ba162c 933 */
segundo 0:ac1725ba162c 934 err_t
segundo 0:ac1725ba162c 935 dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
segundo 0:ac1725ba162c 936 void *callback_arg)
segundo 0:ac1725ba162c 937 {
segundo 0:ac1725ba162c 938 u32_t ipaddr;
segundo 0:ac1725ba162c 939 /* not initialized or no valid server yet, or invalid addr pointer
segundo 0:ac1725ba162c 940 * or invalid hostname or invalid hostname length */
segundo 0:ac1725ba162c 941 if ((dns_pcb == NULL) || (addr == NULL) ||
segundo 0:ac1725ba162c 942 (!hostname) || (!hostname[0]) ||
segundo 0:ac1725ba162c 943 (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
segundo 0:ac1725ba162c 944 return ERR_VAL;
segundo 0:ac1725ba162c 945 }
segundo 0:ac1725ba162c 946
segundo 0:ac1725ba162c 947 #if LWIP_HAVE_LOOPIF
segundo 0:ac1725ba162c 948 if (strcmp(hostname, "localhost")==0) {
segundo 0:ac1725ba162c 949 ip_addr_set_loopback(addr);
segundo 0:ac1725ba162c 950 return ERR_OK;
segundo 0:ac1725ba162c 951 }
segundo 0:ac1725ba162c 952 #endif /* LWIP_HAVE_LOOPIF */
segundo 0:ac1725ba162c 953
segundo 0:ac1725ba162c 954 /* host name already in octet notation? set ip addr and return ERR_OK */
segundo 0:ac1725ba162c 955 ipaddr = ipaddr_addr(hostname);
segundo 0:ac1725ba162c 956 if (ipaddr == IPADDR_NONE) {
segundo 0:ac1725ba162c 957 /* already have this address cached? */
segundo 0:ac1725ba162c 958 ipaddr = dns_lookup(hostname);
segundo 0:ac1725ba162c 959 }
segundo 0:ac1725ba162c 960 if (ipaddr != IPADDR_NONE) {
segundo 0:ac1725ba162c 961 ip4_addr_set_u32(addr, ipaddr);
segundo 0:ac1725ba162c 962 return ERR_OK;
segundo 0:ac1725ba162c 963 }
segundo 0:ac1725ba162c 964
segundo 0:ac1725ba162c 965 /* queue query with specified callback */
segundo 0:ac1725ba162c 966 return dns_enqueue(hostname, found, callback_arg);
segundo 0:ac1725ba162c 967 }
segundo 0:ac1725ba162c 968
segundo 0:ac1725ba162c 969 #endif /* LWIP_DNS */