1 /**
2 * @file
3 * DNS - host name to IP address resolver.
4 *
5 * @defgroup dns DNS
6 * @ingroup callbackstyle_api
7 *
8 * Implements a DNS host name to IP address resolver.
9 *
10 * The lwIP DNS resolver functions are used to lookup a host name and
11 * map it to a numerical IP address. It maintains a list of resolved
12 * hostnames that can be queried with the dns_lookup() function.
13 * New hostnames can be resolved using the dns_query() function.
14 *
15 * The lwIP version of the resolver also adds a non-blocking version of
16 * gethostbyname() that will work with a raw API application. This function
17 * checks for an IP address string first and converts it if it is valid.
18 * gethostbyname() then does a dns_lookup() to see if the name is
19 * already in the table. If so, the IP is returned. If not, a query is
20 * issued and the function returns with a ERR_INPROGRESS status. The app
21 * using the dns client must then go into a waiting state.
22 *
23 * Once a hostname has been resolved (or found to be non-existent),
24 * the resolver code calls a specified callback function (which
25 * must be implemented by the module that uses the resolver).
26 *
27 * Multicast DNS queries are supported for names ending on ".local".
28 * However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762
29 * chapter 5.1), this is not a fully compliant implementation of continuous
30 * mDNS querying!
31 *
32 * All functions must be called from TCPIP thread.
33 *
34 * @see DNS_MAX_SERVERS
35 * @see LWIP_DHCP_MAX_DNS_SERVERS
36 * @see @ref netconn_common for thread-safe access.
37 */
38
39 /*
40 * Port to lwIP from uIP
41 * by Jim Pettinato April 2007
42 *
43 * security fixes and more by Simon Goldschmidt
44 *
45 * uIP version Copyright (c) 2002-2003, Adam Dunkels.
46 * All rights reserved.
47 *
48 * Redistribution and use in source and binary forms, with or without
49 * modification, are permitted provided that the following conditions
50 * are met:
51 * 1. Redistributions of source code must retain the above copyright
52 * notice, this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright
54 * notice, this list of conditions and the following disclaimer in the
55 * documentation and/or other materials provided with the distribution.
56 * 3. The name of the author may not be used to endorse or promote
57 * products derived from this software without specific prior
58 * written permission.
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
61 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
62 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
64 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
66 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
67 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
68 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
69 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
70 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71 */
72
73 /*-----------------------------------------------------------------------------
74 * RFC 1035 - Domain names - implementation and specification
75 * RFC 2181 - Clarifications to the DNS Specification
76 *----------------------------------------------------------------------------*/
77
78 /** @todo: define good default values (rfc compliance) */
79 /** @todo: improve answer parsing, more checkings... */
80 /** @todo: check RFC1035 - 7.3. Processing responses */
81 /** @todo: one-shot mDNS: dual-stack fallback to another IP version */
82
83 /*-----------------------------------------------------------------------------
84 * Includes
85 *----------------------------------------------------------------------------*/
86
87 #include "lwip/opt.h"
88
89 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
90
91 #include "lwip/def.h"
92 #include "lwip/udp.h"
93 #include "lwip/mem.h"
94 #include "lwip/memp.h"
95 #include "lwip/dns.h"
96 #include "lwip/prot/dns.h"
97 #include "lwip/sys.h"
98 #include "arch/sys_arch.h"
99 #include "lwip/tcpip.h"
100 #include "lwip/netdb.h"
101
102 #include <string.h>
103
104 #if LWIP_DNS64 && LWIP_NAT64
105 #include "lwip/nat64.h"
106 #include "lwip/nat64_addr.h"
107 #endif
108
109 #if LWIP_RIPPLE
110 #include "lwip/lwip_rpl.h"
111 #endif
112
113 /** Random generator function to create random TXIDs and source ports for queries */
114 #ifndef DNS_RAND_TXID
115 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) && defined(LWIP_RAND)
116 #define DNS_RAND_TXID LWIP_RAND
117 #else
118 static u16_t dns_txid;
119 #define DNS_RAND_TXID() (++dns_txid)
120 #endif
121 #endif
122
123 /** Limits the source port to be >= 1024 by default */
124 #ifndef DNS_PORT_ALLOWED
125 #define DNS_PORT_ALLOWED(port) ((port) >= 1024)
126 #endif
127
128 /** DNS resource record max. TTL (one week as default) */
129 #ifndef DNS_MAX_TTL
130 #define DNS_MAX_TTL 604800
131 #elif DNS_MAX_TTL > 0x7FFFFFFF
132 #error DNS_MAX_TTL must be a positive 32-bit value
133 #endif
134
135 #if DNS_TABLE_SIZE > 255
136 #error DNS_TABLE_SIZE must fit into an u8_t
137 #endif
138 #if DNS_MAX_SERVERS > 255
139 #error DNS_MAX_SERVERS must fit into an u8_t
140 #endif
141
142 #if LWIP_RIPPLE
143 #define IS_DNS_SERVER_VALID(server) ((!ip_addr_isany(server)) && (!ip_addr_ismulticast(server)) && \
144 (!ip_addr_islinklocal(server)) && (!ip_addr_isloopback(server)))
145 #endif
146
147 /* The number of parallel requests (i.e. calls to dns_gethostbyname
148 * that cannot be answered from the DNS table.
149 * This is set to the table size by default.
150 */
151 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
152 #ifndef DNS_MAX_REQUESTS
153 #define DNS_MAX_REQUESTS DNS_TABLE_SIZE
154 #else
155 #if DNS_MAX_REQUESTS > 255
156 #error DNS_MAX_REQUESTS must fit into an u8_t
157 #endif
158 #endif
159 #else
160 /* In this configuration, both arrays have to have the same size and are used
161 * like one entry (used/free) */
162 #define DNS_MAX_REQUESTS DNS_TABLE_SIZE
163 #endif
164
165 /* The number of UDP source ports used in parallel */
166 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
167 #ifndef DNS_MAX_SOURCE_PORTS
168 #define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
169 #else
170 #if DNS_MAX_SOURCE_PORTS > 255
171 #error DNS_MAX_SOURCE_PORTS must fit into an u8_t
172 #endif
173 #endif
174 #else
175 #ifdef DNS_MAX_SOURCE_PORTS
176 #undef DNS_MAX_SOURCE_PORTS
177 #endif
178 #define DNS_MAX_SOURCE_PORTS 1
179 #endif
180
181 /* This entry is allowed to use this DNS server (unmask this server) */
182 #define DNS_SERVER_SET_AVAILABLE(entry, server_idx) do { \
183 (entry)->server_bitmap &= ~(u32_t)(1 << (server_idx)); \
184 } while (0)
185
186 /* This entry is NOT allowed to use this DNS server in this transaction (mask this server) */
187 #define DNS_SERVER_SET_UNAVAILABLE(entry, server_idx) do { \
188 (entry)->server_bitmap |= (1 << (server_idx)); \
189 } while (0)
190
191 /* Check if this entry is allowed to use this DNS server */
192 #define DNS_SERVER_IS_AVAILABLE(entry, server_idx) \
193 (((entry)->server_bitmap & (1 << (server_idx))) == 0 && !ip_addr_isany(&dns_servers[(server_idx)]))
194
195 /* Switch to the available DNS server when searching */
196 #define DNS_SERVER_SEARCHING_FLAG_SWITCH 0x1
197
198 #if LWIP_DNS_REVERSE
199 #define REVERSE_DOMAIN_MAXLEN 256
200 #endif
201
202 #if LWIP_IPV4 && LWIP_IPV6
203 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6))
204 #define LWIP_DNS_ADDRTYPE_IS_FALLBACK(t) (((t) == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || ((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4))
205 #define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? \
206 (LWIP_DNS_ADDRTYPE_IS_IPV6(t) || LWIP_DNS_ADDRTYPE_IS_FALLBACK(t)) : \
207 (!LWIP_DNS_ADDRTYPE_IS_IPV6(t)) || LWIP_DNS_ADDRTYPE_IS_FALLBACK(t))
208 #define LWIP_DNS_ADDRTYPE_ARG(x) , x
209 #define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x
210 #define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0)
211 #else
212 #if LWIP_IPV6
213 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1
214 #else
215 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0
216 #endif /* LWIP_IPV6 */
217 #define LWIP_DNS_ADDRTYPE_IS_FALLBACK(t) 0
218 #define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1
219 #define LWIP_DNS_ADDRTYPE_ARG(x)
220 #define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0
221 #define LWIP_DNS_SET_ADDRTYPE(x, y)
222 #endif /* LWIP_IPV4 && LWIP_IPV6 */
223
224 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
225 #define LWIP_DNS_ISMDNS_ARG(x) , x
226 #else
227 #define LWIP_DNS_ISMDNS_ARG(x)
228 #endif
229
230 #define LOCALHOST_STRING "localhost"
231
232 /* DNS table entry states */
233 typedef enum {
234 DNS_STATE_UNUSED = 0,
235 DNS_STATE_NEW = 1,
236 DNS_STATE_ASKING = 2,
237 DNS_STATE_DONE = 3
238 } dns_state_enum_t;
239
240 /** DNS table entry */
241 struct dns_table_entry {
242 u32_t ttl;
243 u32_t ipaddr_count;
244 u32_t first_send_time;
245 ip_addr_t ipaddr[DNS_MAX_IPADDR];
246 u16_t txid;
247 u8_t state;
248 u8_t server_idx;
249 u32_t server_bitmap; /* Bitmap for available DNS servers. 0-unmasked, 1-masked */
250 u8_t tmr;
251 u8_t retries;
252 u8_t seqno;
253 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
254 u8_t pcb_idx;
255 #endif
256 char name[DNS_MAX_NAME_LENGTH];
257 #if LWIP_IPV4 && LWIP_IPV6
258 u8_t reqaddrtype;
259 #endif /* LWIP_IPV4 && LWIP_IPV6 */
260 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
261 u8_t is_mdns;
262 #endif
263 };
264
265 #if LWIP_DNS_REVERSE
266 struct reverse_domain {
267 /* Encoded domain name */
268 char name[REVERSE_DOMAIN_MAXLEN];
269 /* Total length of domain name, including zero */
270 size_t length;
271 };
272
273 /* Reverse DNS table entry */
274 struct reverse_dns_table_entry {
275 u32_t ttl;
276 u32_t name_count;
277 u32_t first_send_time;
278 struct reverse_domain encoded_ip;
279 char name[NI_MAXHOST + 1];
280 u16_t txid;
281 u8_t state;
282 u8_t server_idx;
283 u32_t server_bitmap; /* Bitmap for available DNS servers. 0-unmasked, 1-masked */
284 u8_t tmr;
285 u8_t retries;
286 u8_t seqno;
287 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
288 u8_t pcb_idx;
289 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
290 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
291 u8_t is_mdns;
292 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
293 };
294 #endif
295
296 /** DNS request table entry: used when dns_gethostbyname cannot answer the
297 * request from the DNS table */
298 struct dns_req_entry {
299 /* pointer to callback on DNS query done */
300 dns_found_callback found;
301 /* argument passed to the callback function */
302 void *arg;
303 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
304 u8_t dns_table_idx;
305 #endif
306 #if LWIP_IPV4 && LWIP_IPV6
307 u8_t reqaddrtype;
308 #endif /* LWIP_IPV4 && LWIP_IPV6 */
309 };
310
311 #if LWIP_DNS_REVERSE
312 /* Reverse DNS request table entry: used when reverse_dns_getnamebyhost cannot answer the
313 * request from the Reverse DNS table */
314 struct reverse_dns_req_entry {
315 /* pointer to callback on DNS query done */
316 reverse_dns_found_callback found;
317 /* argument passed to the callback function */
318 void *arg;
319 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
320 u8_t reverse_dns_table_idx;
321 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0 */
322 };
323 #endif
324
325 #if DNS_LOCAL_HOSTLIST
326
327 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
328 /** Local host-list. For hostnames in this list, no
329 * external name resolution is performed */
330 static struct local_hostlist_entry *local_hostlist_dynamic;
331 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
332
333 /** Defining this allows the local_hostlist_static to be placed in a different
334 * linker section (e.g. FLASH) */
335 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
336 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
337 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
338 /** Defining this allows the local_hostlist_static to be placed in a different
339 * linker section (e.g. FLASH) */
340 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
341 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
342 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
343 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
344 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
345
346 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
347
348 static void dns_init_local(void);
349 static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
350 #endif /* DNS_LOCAL_HOSTLIST */
351
352
353 /* forward declarations */
354 static err_t dns_send(u8_t idx);
355 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
356
357 static void process_forward_dns(struct pbuf *p, u8_t entry_idx, struct dns_table_entry *entry, struct dns_hdr hdr,
358 const ip_addr_t *addr);
359 static err_t dns_check_entry(u8_t i);
360 static void dns_check_entries(void);
361 static void dns_correct_response(u8_t idx, u32_t ttl);
362 static void dns_call_found(u8_t idx, const ip_addr_t *addr, u32_t ipaddr_count);
363 static u16_t dns_create_txid(void);
364 static void dns_find_first_server(void);
365
366 static err_t
367 dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
368 void *callback_arg, u8_t dns_addrtype LWIP_DNS_ISMDNS_ARG(u8_t is_mdns));
369 static u8_t
370 dns_backupserver_available(struct dns_table_entry *pentry, u8_t flags);
371
372 static u16_t
373 dns_compare_name(char *query, struct pbuf *p, u16_t start_offset, u16_t allow_compressed_hdr);
374 static err_t
375 dns_lookup(const char *name, ip_addr_t *addr, u32_t *count LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype));
376
377 #if LWIP_DNS_REVERSE
378 #ifdef LWIP_TESTBED
379 err_t reverse_dns_domain_add_label(struct reverse_domain *domain, const char *label, size_t len);
380 #else
381 static err_t reverse_dns_domain_add_label(struct reverse_domain *domain, const char *label, size_t len);
382 #endif
383
384 #if LWIP_IPV4
385 static err_t reverse_dns_build_reverse_v4_domain(struct reverse_domain *domain, const ip4_addr_t *addr);
386 #endif /* LWIP_IPV4 */
387
388 #if LWIP_IPV6
389 static err_t reverse_dns_build_reverse_v6_domain(struct reverse_domain *domain, const ip6_addr_t *addr);
390 #endif /* LWIP_IPV6 */
391
392 static void process_reverse_dns(struct pbuf *p, u8_t entry_idx, struct reverse_dns_table_entry *reverse_entry,
393 struct dns_hdr hdr, const ip_addr_t *addr);
394
395 static void reverse_dns_check_entries(void);
396 static err_t reverse_dns_lookup(const struct reverse_domain *encoded_ip, char *hostname);
397 static err_t reverse_dns_send(u8_t idx);
398 static void reverse_dns_call_found(u8_t idx, const char *hostname, u32_t name_count);
399 static err_t reverse_dns_check_entry(u8_t i);
400 static void reverse_dns_correct_response(u8_t idx, u32_t ttl);
401 static err_t reverse_dns_enqueue(const struct reverse_domain *encoded_ip, reverse_dns_found_callback found,
402 void *callback_arg);
403 static u8_t reverse_dns_backupserver_available(struct reverse_dns_table_entry *rentry, u8_t flags);
404 #endif /* LWIP_DNS_REVERSE */
405
406 /*-----------------------------------------------------------------------------
407 * Globals
408 *----------------------------------------------------------------------------*/
409
410 /* DNS variables */
411 static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS];
412 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
413 static u8_t dns_last_pcb_idx;
414 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
415 static u8_t dns_seqno = 0;
416 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
417 static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
418 static ip_addr_t dns_servers[DNS_MAX_SERVERS];
419
420 #if LWIP_DNS_REVERSE
421 static struct reverse_dns_table_entry reverse_dns_table[DNS_TABLE_SIZE];
422 static struct reverse_dns_req_entry reverse_dns_requests[DNS_MAX_REQUESTS];
423 #endif /* LWIP_DNS_REVERSE */
424
425 #if LWIP_IPV4
426 const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT;
427 #endif /* LWIP_IPV4 */
428 #if LWIP_IPV6
429 const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT;
430 #endif /* LWIP_IPV6 */
431
432 static u8_t dns_first_server_idx = 0;
433 #if LWIP_DNS_REVERSE
434 static u8_t rdns_first_server_idx = 0;
435 #endif /* LWIP_DNS_REVERSE */
436 struct dns_msg {
437 u8_t numdns;
438 ip_addr_t *dnsserver;
439 sys_sem_t cb_completed;
440 };
441
442 /**
443 * Initialize the resolver: set up the UDP pcb and configure the default server
444 * (if DNS_SERVER_ADDRESS is set).
445 */
446 void
dns_init(void)447 dns_init(void)
448 {
449 #ifdef DNS_SERVER_ADDRESS
450 /* initialize default DNS server address */
451 ip_addr_t dnsserver;
452 DNS_SERVER_ADDRESS(&dnsserver);
453 dns_setserver(0, &dnsserver);
454 #endif /* DNS_SERVER_ADDRESS */
455
456 LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
457 sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
458 LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER",
459 sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT);
460
461 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
462
463 /* if dns client not yet initialized... */
464 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
465 if (dns_pcbs[0] == NULL) {
466 dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY);
467 LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL);
468
469 /* initialize DNS table not needed (initialized to zero since it is a
470 * global variable) */
471 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
472 DNS_STATE_UNUSED == 0);
473
474 #if LWIP_SO_PRIORITY
475 dns_pcbs[0]->priority = LWIP_PKT_PRIORITY_DNS;
476 #endif /* LWIP_SO_PRIORITY */
477
478 /* initialize DNS client */
479 udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0);
480 udp_recv(dns_pcbs[0], dns_recv, NULL);
481 }
482 #endif
483
484 #if DNS_LOCAL_HOSTLIST
485 dns_init_local();
486 #endif
487 }
488
489 /**
490 * @ingroup dns
491 * Initialize one of the DNS servers.
492 *
493 * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
494 * @param dnsserver IP address of the DNS server to set
495 */
496 void
dns_setserver(u8_t numdns,const ip_addr_t * dnsserver)497 dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
498 {
499 u8_t i;
500 #if LWIP_RIPPLE
501 u8_t changed = 0;
502 u8_t cnt;
503 ip_addr_t server;
504 #endif
505 if (numdns < DNS_MAX_SERVERS) {
506 #if LWIP_RIPPLE
507 server = dns_servers[numdns];
508 #endif
509 if (dnsserver != NULL) {
510 dns_servers[numdns] = (*dnsserver);
511 } else {
512 dns_servers[numdns] = *IP_ADDR_ANY;
513 }
514
515 /* once any change of DNS server happens, simply set it available here,
516 and check if it is a valid server when searching for first_server and backup_server. */
517 for (i = 0; i < DNS_TABLE_SIZE; i++) {
518 dns_table[i].server_bitmap = 0;
519 #if LWIP_DNS_REVERSE
520 reverse_dns_table[i].server_bitmap = 0;
521 #endif /* LWIP_DNS_REVERSE */
522 }
523
524 /* once any changes of DNS servers, refind the first server */
525 dns_find_first_server();
526 #if LWIP_RIPPLE
527 if ((dnsserver != NULL) && IS_DNS_SERVER_VALID(dnsserver) &&
528 (memcmp(&server, dnsserver, sizeof(ip_addr_t)) != 0)) {
529 changed = 1;
530 } else if ((dnsserver == NULL) && IS_DNS_SERVER_VALID(&server)) {
531 cnt = lwip_dns_get_server_cnt(NULL, NULL);
532 if (cnt > 0) {
533 changed = 1;
534 }
535 }
536
537 if (changed == 1) {
538 #ifdef LWIP_DNS_RPL_REPAIR
539 lwip_rpl_trigger_global_repair();
540 #else
541 lwip_rpl_trigger_global_dao();
542 #endif
543 }
544 #endif
545 }
546 }
547
548 void
dns_setserver_internal(void * arg)549 dns_setserver_internal(void *arg)
550 {
551 struct dns_msg *msg = NULL;
552
553 msg = (struct dns_msg *)arg;
554
555 dns_setserver(msg->numdns, msg->dnsserver);
556 sys_sem_signal(&msg->cb_completed);
557 }
558
559 err_t
lwip_dns_setserver(u8_t numdns,ip_addr_t * dnsserver)560 lwip_dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
561 {
562 struct dns_msg dmsg;
563 err_t err;
564
565 (void)memset_s(&dmsg, sizeof(dmsg), 0, sizeof(dmsg));
566 if (numdns >= DNS_MAX_SERVERS) {
567 LWIP_DEBUGF(DNS_DEBUG, ("lwip_dns_setserver: Invalid param, index %"S32_F", "
568 "DNS_MAX_SERVERS is %"S32_F"\n", numdns, DNS_MAX_SERVERS));
569 return ERR_VAL;
570 }
571
572 dmsg.numdns = numdns;
573 dmsg.dnsserver = dnsserver;
574
575 err = sys_sem_new(&dmsg.cb_completed, 0);
576 if (err != ERR_OK) {
577 return err;
578 }
579
580 err = tcpip_callback(dns_setserver_internal, &dmsg);
581 if (err != ERR_OK) {
582 sys_sem_free(&dmsg.cb_completed);
583 return err;
584 }
585
586 (void)sys_arch_sem_wait(&dmsg.cb_completed, 0);
587 sys_sem_free(&dmsg.cb_completed);
588
589 return ERR_OK;
590 }
591
592 /**
593 * @ingroup dns
594 * Obtain one of the currently configured DNS server.
595 *
596 * @param numdns the index of the DNS server
597 * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
598 * server has not been configured.
599 */
600 const ip_addr_t*
dns_getserver(u8_t numdns)601 dns_getserver(u8_t numdns)
602 {
603 if (numdns < DNS_MAX_SERVERS) {
604 return &dns_servers[numdns];
605 } else {
606 return IP_ADDR_ANY;
607 }
608 }
609
610 void
dns_getserver_internal(void * arg)611 dns_getserver_internal(void *arg)
612 {
613 struct dns_msg *msg = NULL;
614
615 msg = (struct dns_msg *)arg;
616
617 *msg->dnsserver = *dns_getserver(msg->numdns);
618 sys_sem_signal(&msg->cb_completed);
619 }
620
621 err_t
lwip_dns_getserver(u8_t numdns,ip_addr_t * dnsserver)622 lwip_dns_getserver(u8_t numdns, ip_addr_t *dnsserver)
623 {
624 struct dns_msg dmsg;
625 err_t err;
626
627 (void)memset_s(&dmsg, sizeof(dmsg), 0, sizeof(dmsg));
628 if (dnsserver == NULL) {
629 LWIP_DEBUGF(DNS_DEBUG, ("lwip_dns_setserver: Invalid param, dnsserver 0x%p\n", (void *)dnsserver));
630 return ERR_VAL;
631 }
632
633 dmsg.numdns = numdns;
634 dmsg.dnsserver = dnsserver;
635
636 err = sys_sem_new(&dmsg.cb_completed, 0);
637 if (err != ERR_OK) {
638 return err;
639 }
640
641 err = tcpip_callback(dns_getserver_internal, &dmsg);
642 if (err != ERR_OK) {
643 sys_sem_free(&dmsg.cb_completed);
644 return err;
645 }
646
647 (void)sys_arch_sem_wait(&dmsg.cb_completed, 0);
648 sys_sem_free(&dmsg.cb_completed);
649
650 return ERR_OK;
651 }
652
653 u8_t
lwip_dns_get_server_cnt(u8_t * ip4cnt,u8_t * ip6cnt)654 lwip_dns_get_server_cnt(u8_t *ip4cnt, u8_t *ip6cnt)
655 {
656 int i;
657 u8_t cnt = 0;
658
659 if (ip4cnt != NULL) {
660 *ip4cnt = 0;
661 }
662
663 if (ip6cnt != NULL) {
664 *ip6cnt = 0;
665 }
666
667 for (i = 0; i < DNS_MAX_SERVERS; i++) {
668 if (ip_addr_isany_val(dns_servers[i])) {
669 continue;
670 }
671
672 cnt++;
673 if (IP_IS_V6_VAL(dns_servers[i])) {
674 (ip6cnt != NULL) ? (*ip6cnt)++ : 0;
675 } else if (ip4cnt != NULL) {
676 (*ip4cnt)++;
677 }
678 }
679
680 return cnt;
681 }
682
683 #if LWIP_IPV6
684 err_t
lwip_dns_copy_ip6server_addr(const struct netif * nif,ip6_addr_t * ip6addr,u8_t num)685 lwip_dns_copy_ip6server_addr(const struct netif *nif, ip6_addr_t *ip6addr, u8_t num)
686 {
687 int i;
688 int cnt = 0;
689
690 if ((nif == NULL) || (ip6addr == NULL) || (num == 0)) {
691 return ERR_ARG;
692 }
693
694 for (i = 0; i < DNS_MAX_SERVERS; i++) {
695 if (ip_addr_isany_val(dns_servers[i])) {
696 continue;
697 }
698
699 if (IP_IS_V6_VAL(dns_servers[i]) && (!ip_addr_isloopback(&dns_servers[i])) &&
700 (!ip_addr_ismulticast(&dns_servers[i])) && (!ip_addr_islinklocal(&dns_servers[i]))) {
701 ip6_addr_copy(ip6addr[cnt], *ip_2_ip6(&dns_servers[i]));
702 cnt++;
703 if (cnt >= num) {
704 return ERR_OK;
705 }
706 continue;
707 }
708 #if LWIP_RIPPLE && LWIP_DNS64 && LWIP_NAT64
709 if ((lwip_rpl_is_rpl_netif(nif) == lwIP_TRUE) && (lwip_rpl_is_br() == lwIP_TRUE) &&
710 (nat64_status_check() == NAT64_RET_OK) && IP_IS_V4_VAL(dns_servers[i]) &&
711 (nat64_stateless_addr_4to6(ip_2_ip4(&dns_servers[i]), &ip6addr[cnt]) == ERR_OK)) {
712 cnt++;
713 if (cnt >= num) {
714 return ERR_OK;
715 }
716 }
717 #endif
718 }
719
720 if (cnt != num) {
721 return ERR_VAL;
722 }
723
724 return ERR_OK;
725 }
726 #endif
727
728 #if LWIP_DNS_REVERSE
729 /*
730 * Add a label part to a domain
731 * @param domain The domain to add a label to
732 * @param label The label to add, like <hostname>, 'local', 'com' or ''
733 * @param len The length of the label
734 * @return ERR_OK on success, an err_t otherwise if label too long
735 */
736 #ifdef LWIP_TESTBED
737 err_t
738 #else
739 static err_t
740 #endif
reverse_dns_domain_add_label(struct reverse_domain * domain,const char * label,size_t len)741 reverse_dns_domain_add_label(struct reverse_domain *domain, const char *label, size_t len)
742 {
743 if (len > DNS_MAX_LABEL_LENGTH) {
744 return ERR_VAL;
745 }
746 if ((len > 0) && (1 + len + domain->length >= REVERSE_DOMAIN_MAXLEN)) {
747 return ERR_VAL;
748 }
749 /* Allow only zero marker on last byte */
750 if ((len == 0) && (1 + domain->length > REVERSE_DOMAIN_MAXLEN)) {
751 return ERR_VAL;
752 }
753 if ((domain->length != 0) && (label != NULL)) {
754 domain->name[domain->length] = '.';
755 domain->length++;
756 }
757 if ((len != 0) && (label != NULL)) {
758 if (memcpy_s(&domain->name[domain->length], (REVERSE_DOMAIN_MAXLEN - domain->length), label, len) != EOK) {
759 return ERR_MEM;
760 }
761 domain->length += len;
762 }
763 return ERR_OK;
764 }
765
766
767 #if LWIP_IPV4
768 /*
769 * Build domain for reverse lookup of IPv4 address
770 * 192.168.0.12 will be mapped to 12.0.168.192.in-addr.arpa.
771 * @param domain Where to write the domain name
772 * @param addr Pointer to an IPv4 address to encode
773 * @return ERR_OK if domain was written, an err_t otherwise
774 */
775 static err_t
reverse_dns_build_reverse_v4_domain(struct reverse_domain * domain,const ip4_addr_t * addr)776 reverse_dns_build_reverse_v4_domain(struct reverse_domain *domain, const ip4_addr_t *addr)
777 {
778 int i;
779 err_t res;
780 const u8_t *ptr = NULL;
781 /* ip4 address have 4 parts, biggges parts is 255, less than 4 */
782 char buf[4];
783 u8_t val;
784
785 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: domain is NULL", (domain != NULL), return ERR_ARG);
786 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: addr is NULL", (addr != NULL), return ERR_ARG);
787
788 (void)memset_s(domain, sizeof(struct reverse_domain), 0, sizeof(struct reverse_domain));
789
790 ptr = (const u8_t *)addr;
791 for (i = (int)(sizeof(ip4_addr_t)) - 1; i >= 0; --i) {
792 val = ptr[i];
793 lwip_itoa(buf, sizeof(buf), val);
794 res = reverse_dns_domain_add_label(domain, buf, strlen(buf));
795 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: Failed to add label: buf", (res == ERR_OK), return res);
796 }
797 res = reverse_dns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (sizeof(REVERSE_PTR_V4_DOMAIN)-1));
798 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: Failed to add label: REVERSE_PTR_V4_DOMAIN",
799 (res == ERR_OK), return res);
800 res = reverse_dns_domain_add_label(domain, REVERSE_PTR_TOP_DOMAIN, (sizeof(REVERSE_PTR_TOP_DOMAIN)-1));
801 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: Failed to add label: REVERSE_PTR_TOP_DOMAIN",
802 (res == ERR_OK), return res);
803 res = reverse_dns_domain_add_label(domain, NULL, 0);
804 LWIP_ERROR("reverse_dns_build_reverse_v4_domain: Failed to add label: NULL", (res == ERR_OK), return res);
805
806 return ERR_OK;
807 }
808 #endif /* LWIP_IPV4 */
809
810 #if LWIP_IPV6
811 /*
812 * Build domain for reverse lookup of IP address
813 * 2001:db8::567:89ab will be mapped to b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
814 * @param domain Where to write the domain name
815 * @param addr Pointer to an IPv6 address to encode
816 * @return ERR_OK if domain was written, an err_t otherwise
817 */
818 static err_t
reverse_dns_build_reverse_v6_domain(struct reverse_domain * domain,const ip6_addr_t * addr)819 reverse_dns_build_reverse_v6_domain(struct reverse_domain *domain, const ip6_addr_t *addr)
820 {
821 int i;
822 int j;
823 err_t res;
824 u8_t byte;
825 char buf;
826 const u8_t *ptr = NULL;
827
828 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: domain is NULL", (domain != NULL), return ERR_ARG);
829 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: addr is NULL", (addr != NULL), return ERR_ARG);
830
831 (void)memset_s(domain, sizeof(struct reverse_domain), 0, sizeof(struct reverse_domain));
832
833 ptr = (const u8_t *)addr;
834 for (i = (int)(sizeof(ip6_addr_t)) - 1; i >= 0; i--) {
835 byte = ptr[i];
836 /* each byte have 2 nibbles */
837 for (j = 0; j < 2; j++) {
838 if ((byte & 0x0F) < 0xA) {
839 buf = (char)('0' + (byte & 0x0F));
840 } else {
841 buf = (char)('a' + (byte & 0x0F) - (0xA));
842 }
843 res = reverse_dns_domain_add_label(domain, &buf, sizeof(buf));
844 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: Failed to add label: buf", (res == ERR_OK), return res);
845 /* get next nibble */
846 byte >>= 4;
847 }
848 }
849 res = reverse_dns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (sizeof(REVERSE_PTR_V6_DOMAIN)-1));
850 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: Failed to add label: REVERSE_PTR_V6_DOMAIN",
851 (res == ERR_OK), return res);
852 res = reverse_dns_domain_add_label(domain, REVERSE_PTR_TOP_DOMAIN, (sizeof(REVERSE_PTR_TOP_DOMAIN)-1));
853 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: Failed to add label: REVERSE_PTR_TOP_DOMAIN",
854 (res == ERR_OK), return res);
855 res = reverse_dns_domain_add_label(domain, NULL, 0);
856 LWIP_ERROR("reverse_dns_build_reverse_v6_domain: Failed to add label: NULL", (res == ERR_OK), return res);
857
858 return ERR_OK;
859 }
860 #endif /* LWIP_IPV6 */
861 #endif /* LWIP_DNS_REVERSE */
862
863 /*
864 * The DNS resolver client timer - handle retries and timeouts and should
865 * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
866 */
867 void
dns_tmr(void)868 dns_tmr(void)
869 {
870 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
871 dns_check_entries();
872 #if LWIP_DNS_REVERSE
873 reverse_dns_check_entries();
874 #endif /* LWIP_DNS_REVERSE */
875 }
876
877 #if LWIP_LOWPOWER
878 #include "lwip/lowpower.h"
879 u32_t
dns_tmr_tick(void)880 dns_tmr_tick(void)
881 {
882 u32_t tick = 0;
883 u32_t val;
884 s32_t i;
885
886 for (i = 0; i < DNS_TABLE_SIZE; i++) {
887 if ((dns_table[i].state == DNS_STATE_NEW) ||
888 (dns_table[i].state == DNS_STATE_ASKING)) {
889 LOWPOWER_DEBUG(("%s tmr tick: 1\n", __func__));
890 return 1;
891 }
892 if (dns_table[i].state == DNS_STATE_DONE) {
893 val = dns_table[i].ttl;
894 SET_TMR_TICK(tick, val);
895 }
896 #if LWIP_DNS_REVERSE
897 if ((reverse_dns_table[i].state == DNS_STATE_NEW) ||
898 (reverse_dns_table[i].state == DNS_STATE_ASKING)) {
899 LOWPOWER_DEBUG(("%s tmr tick: 1\n", __func__));
900 return 1;
901 }
902 if (reverse_dns_table[i].state == DNS_STATE_DONE) {
903 val = reverse_dns_table[i].ttl;
904 SET_TMR_TICK(tick, val);
905 }
906 #endif /* LWIP_DNS_REVERSE */
907 }
908 LOWPOWER_DEBUG(("%s tmr tick: %u\n", __func__, tick));
909 return tick;
910 }
911 #endif
912
913 #if DNS_LOCAL_HOSTLIST
914 static void
dns_init_local(void)915 dns_init_local(void)
916 {
917 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
918 size_t i;
919 struct local_hostlist_entry *entry;
920 /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
921 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
922 size_t namelen;
923 for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) {
924 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
925 LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
926 namelen = strlen(init_entry->name);
927 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
928 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
929 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
930 if (entry != NULL) {
931 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
932 MEMCPY((char*)entry->name, init_entry->name, namelen);
933 ((char*)entry->name)[namelen] = 0;
934 entry->addr = init_entry->addr;
935 entry->next = local_hostlist_dynamic;
936 local_hostlist_dynamic = entry;
937 }
938 }
939 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
940 }
941
942 /**
943 * @ingroup dns
944 * Iterate the local host-list for a hostname.
945 *
946 * @param iterator_fn a function that is called for every entry in the local host-list
947 * @param iterator_arg 3rd argument passed to iterator_fn
948 * @return the number of entries in the local host-list
949 */
950 size_t
dns_local_iterate(dns_found_callback iterator_fn,void * iterator_arg)951 dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg)
952 {
953 size_t i;
954 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
955 struct local_hostlist_entry *entry = local_hostlist_dynamic;
956 i = 0;
957 while (entry != NULL) {
958 if (iterator_fn != NULL) {
959 iterator_fn(entry->name, &entry->addr, 1, iterator_arg);
960 }
961 i++;
962 entry = entry->next;
963 }
964 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
965 for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
966 if (iterator_fn != NULL) {
967 iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, 1, iterator_arg);
968 }
969 }
970 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
971 return i;
972 }
973
974 /**
975 * @ingroup dns
976 * Scans the local host-list for a hostname.
977 *
978 * @param hostname Hostname to look for in the local host-list
979 * @param addr the first IP address for the hostname in the local host-list or
980 * IPADDR_NONE if not found.
981 * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!)
982 * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!)
983 * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
984 * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
985 * @return ERR_OK if found, ERR_ARG if not found
986 */
987 err_t
dns_local_lookup(const char * hostname,ip_addr_t * addr,u8_t dns_addrtype)988 dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype)
989 {
990 LWIP_UNUSED_ARG(dns_addrtype);
991 return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
992 }
993
994 /* Internal implementation for dns_local_lookup and dns_lookup */
995 static err_t
dns_lookup_local(const char * hostname,ip_addr_t * addr LWIP_DNS_ADDRTYPE_ARG (u8_t dns_addrtype))996 dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
997 {
998 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
999 struct local_hostlist_entry *entry = local_hostlist_dynamic;
1000 while (entry != NULL) {
1001 if ((lwip_stricmp(entry->name, hostname) == 0) &&
1002 LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) {
1003 if (addr) {
1004 ip_addr_copy(*addr, entry->addr);
1005 }
1006 return ERR_OK;
1007 }
1008 entry = entry->next;
1009 }
1010 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
1011 size_t i;
1012 for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) {
1013 if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) &&
1014 LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) {
1015 if (addr) {
1016 ip_addr_copy(*addr, local_hostlist_static[i].addr);
1017 }
1018 return ERR_OK;
1019 }
1020 }
1021 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
1022 return ERR_ARG;
1023 }
1024
1025 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
1026 /**
1027 * @ingroup dns
1028 * Remove all entries from the local host-list for a specific hostname
1029 * and/or IP address
1030 *
1031 * @param hostname hostname for which entries shall be removed from the local
1032 * host-list
1033 * @param addr address for which entries shall be removed from the local host-list
1034 * @return the number of removed entries
1035 */
1036 int
dns_local_removehost(const char * hostname,const ip_addr_t * addr)1037 dns_local_removehost(const char *hostname, const ip_addr_t *addr)
1038 {
1039 int removed = 0;
1040 struct local_hostlist_entry *entry = local_hostlist_dynamic;
1041 struct local_hostlist_entry *last_entry = NULL;
1042 while (entry != NULL) {
1043 if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) &&
1044 ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
1045 struct local_hostlist_entry *free_entry;
1046 if (last_entry != NULL) {
1047 last_entry->next = entry->next;
1048 } else {
1049 local_hostlist_dynamic = entry->next;
1050 }
1051 free_entry = entry;
1052 entry = entry->next;
1053 memp_free(MEMP_LOCALHOSTLIST, free_entry);
1054 removed++;
1055 } else {
1056 last_entry = entry;
1057 entry = entry->next;
1058 }
1059 }
1060 return removed;
1061 }
1062
1063 /**
1064 * @ingroup dns
1065 * Add a hostname/IP address pair to the local host-list.
1066 * Duplicates are not checked.
1067 *
1068 * @param hostname hostname of the new entry
1069 * @param addr IP address of the new entry
1070 * @return ERR_OK if succeeded or ERR_MEM on memory error
1071 */
1072 err_t
dns_local_addhost(const char * hostname,const ip_addr_t * addr)1073 dns_local_addhost(const char *hostname, const ip_addr_t *addr)
1074 {
1075 struct local_hostlist_entry *entry;
1076 size_t namelen;
1077 LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
1078 namelen = strlen(hostname);
1079 LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
1080 entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
1081 if (entry == NULL) {
1082 return ERR_MEM;
1083 }
1084 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
1085 MEMCPY((char*)entry->name, hostname, namelen);
1086 ((char*)entry->name)[namelen] = 0;
1087
1088 ip_addr_copy(entry->addr, *addr);
1089 entry->next = local_hostlist_dynamic;
1090 local_hostlist_dynamic = entry;
1091 return ERR_OK;
1092 }
1093 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
1094 #endif /* DNS_LOCAL_HOSTLIST */
1095
1096 /**
1097 * @ingroup dns
1098 * Look up a hostname in the array of known hostnames.
1099 *
1100 * @note This function only looks in the internal array of known
1101 * hostnames, it does not send out a query for the hostname if none
1102 * was found. The function dns_enqueue() can be used to send a query
1103 * for a hostname.
1104 *
1105 * @param name the hostname to look up
1106 * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to
1107 * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
1108 * was not found in the cached dns_table.
1109 * @param count the maximum number of resolved IP Address requested for name
1110 * @return ERR_OK if found, ERR_ARG if not found
1111 */
1112 static err_t
dns_lookup(const char * name,ip_addr_t * addr,u32_t * count LWIP_DNS_ADDRTYPE_ARG (u8_t dns_addrtype))1113 dns_lookup(const char *name, ip_addr_t *addr, u32_t *count LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
1114 {
1115 u8_t i;
1116 u8_t j;
1117 u8_t matching_response = 0;
1118 #if DNS_LOCAL_HOSTLIST
1119 if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
1120 *count = 1;
1121 return ERR_OK;
1122 }
1123 #endif /* DNS_LOCAL_HOSTLIST */
1124 #ifdef DNS_LOOKUP_LOCAL_EXTERN
1125 if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) {
1126 *count = 1;
1127 return ERR_OK;
1128 }
1129 #endif /* DNS_LOOKUP_LOCAL_EXTERN */
1130
1131 /* Walk through name list, return entry if found. If not, return NULL. */
1132 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1133 if ((dns_table[i].state == DNS_STATE_DONE) &&
1134 (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) {
1135
1136 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup : found = \"%s\"", name));
1137
1138 for (j = 0; j < LWIP_MIN(*count, dns_table[i].ipaddr_count); j++) {
1139 if (LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr[j])) {
1140 #ifdef LWIP_DEV_DEBUG
1141 ip_addr_debug_print_val(DNS_DEBUG, dns_table[i].ipaddr[j]);
1142 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
1143 #endif /* LWIP_DEV_DEBUG */
1144 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup : found = \"%s\" with matching ADDRTYPE\n", name));
1145 ip_addr_copy(addr[matching_response], dns_table[i].ipaddr[j]);
1146 ++matching_response;
1147 }
1148 }
1149
1150 if (matching_response == 0) {
1151 continue;
1152 }
1153
1154 *count = matching_response;
1155 return ERR_OK;
1156 }
1157 }
1158
1159 return ERR_ARG;
1160 }
1161
1162 #if LWIP_DNS_REVERSE
1163 static err_t
reverse_dns_lookup(const struct reverse_domain * encoded_ip,char * hostname)1164 reverse_dns_lookup(const struct reverse_domain *encoded_ip, char *hostname)
1165 {
1166 u8_t i;
1167
1168 /* Walk through name list, return entry if found. If not, return NULL. */
1169 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1170 if ((reverse_dns_table[i].state == DNS_STATE_DONE) &&
1171 (lwip_strnicmp((const char*)(encoded_ip->name), (const char*)(reverse_dns_table[i].encoded_ip.name),
1172 sizeof(reverse_dns_table[i].encoded_ip.name)) == 0)) {
1173 if (strncpy_s(hostname, NI_MAXHOST, reverse_dns_table[i].name, strlen(reverse_dns_table[i].name)) != EOK) {
1174 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_lookup : memory error\n"));
1175 return ERR_MEM;
1176 }
1177 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_lookup : found = \"%s\"\n", hostname));
1178
1179 return ERR_OK;
1180 }
1181 }
1182 return ERR_ARG;
1183 }
1184 #endif /* LWIP_DNS_REVERSE */
1185
1186 /**
1187 * Compare the "dotted" name "query" with the encoded name "response"
1188 * to make sure an answer from the DNS server matches the current dns_table
1189 * entry (otherwise, answers might arrive late for hostname not on the list
1190 * any more).
1191 *
1192 * For now, this function compares case-insensitive to cope with all kinds of
1193 * servers. This also means that "dns 0x20 bit encoding" must be checked
1194 * externally, if we want to implement it.
1195 * Currently, the request is sent exactly as passed in by he user request.
1196 *
1197 * @param query hostname (not encoded) from the dns_table
1198 * @param p pbuf containing the encoded hostname in the DNS response
1199 * @param start_offset offset into p where the name starts
1200 * @return 0xFFFF: names differ, other: names equal -> offset behind name
1201 */
1202 static u16_t
dns_compare_name(char * query,struct pbuf * p,u16_t start_offset,u16_t allow_compressed_hdr)1203 dns_compare_name(char *query, struct pbuf *p, u16_t start_offset, u16_t allow_compressed_hdr)
1204 {
1205 unsigned char n;
1206 u16_t response_offset = start_offset;
1207 u16_t ret;
1208
1209 do {
1210 n = (u8_t)pbuf_try_get_at(p, response_offset);
1211 if (!n) {
1212 /* error or overflow */
1213 return 0xFFFF;
1214 }
1215 response_offset++;
1216 /** @see RFC 1035 - 4.1.4. Message compression */
1217 if (((n & 0xc0) == 0xc0) && (response_offset == (start_offset + 1)) && (allow_compressed_hdr)) {
1218 /* Compressed name: cannot be equal since we don't send them */
1219 n = (u8_t)pbuf_try_get_at(p, response_offset);
1220
1221 if (!n) {
1222 /* if the offset of compressed hdr is 0, fail from here */
1223 return 0xFFFF;
1224 }
1225
1226 ret = dns_compare_name(query, p, (u16_t)n, 0);
1227 if (ret == 0xFFFF) {
1228 return 0xFFFF;
1229 } else if (ret == n) {
1230 return start_offset;
1231 } else {
1232 return (u16_t)(response_offset + (u16_t)1);
1233 }
1234 } else if (n > DNS_MAX_LABEL_LENGTH) {
1235 return 0xFFFF;
1236 } else {
1237 /* Not compressed name */
1238 while ((n > 0) && (*query != 0)) {
1239 u8_t c = pbuf_get_at(p, response_offset);
1240 if (lwip_tolower((*query)) != lwip_tolower((u8_t)c)) {
1241 return start_offset;
1242 }
1243 response_offset++;
1244 ++query;
1245 --n;
1246 }
1247 if (*query) {
1248 ++query;
1249 }
1250 }
1251 } while ((pbuf_get_at(p, response_offset) != 0) && (*query != 0));
1252
1253 if (response_offset > p->tot_len) {
1254 return 0xFFFF;
1255 }
1256 if ((pbuf_get_at(p, response_offset) == 0) && (*query == 0) && (n == 0)) {
1257 return (u16_t)(response_offset + (u16_t)1);
1258 }
1259 return start_offset;
1260 }
1261
1262 /**
1263 * Walk through a compact encoded DNS name and return the end of the name.
1264 *
1265 * @param p pbuf containing the name
1266 * @param query_idx start index into p pointing to encoded DNS name in the DNS server response
1267 * @return index to end of the name
1268 */
1269 u16_t
dns_skip_name(const struct pbuf * p,u16_t query_idx)1270 dns_skip_name(const struct pbuf *p, u16_t query_idx)
1271 {
1272 int n;
1273 u16_t offset = query_idx;
1274
1275 do {
1276 n = pbuf_try_get_at(p, offset++);
1277 if ((n < 0) || (offset == 0)) {
1278 return 0xFFFF;
1279 }
1280 /** @see RFC 1035 - 4.1.4. Message compression */
1281 if ((n & 0xc0) == 0xc0) {
1282 /* Compressed name: since we only want to skip it (not check it), stop here */
1283 break;
1284 } else if (n > DNS_MAX_LABEL_LENGTH) {
1285 return 0xFFFF;
1286 } else if (offset + n >= p->tot_len) {
1287 /* Not compressed name */
1288 return 0xFFFF;
1289 } else {
1290 offset = (u16_t)(offset + n);
1291 }
1292 n = pbuf_try_get_at(p, offset);
1293 if (n < 0) {
1294 return 0xFFFF;
1295 }
1296 } while (n != 0);
1297
1298 if (offset == 0xFFFF) {
1299 return 0xFFFF;
1300 }
1301 return (u16_t)(offset + 1);
1302 }
1303
1304 /**
1305 * Send a DNS query packet.
1306 *
1307 * @param idx the DNS table entry index for which to send a request
1308 * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
1309 */
1310 static err_t
dns_send(u8_t idx)1311 dns_send(u8_t idx)
1312 {
1313 err_t err;
1314 struct dns_hdr hdr;
1315 struct dns_query qry;
1316 struct pbuf *p;
1317 u16_t query_idx, copy_len;
1318 const char *hostname, *hostname_part;
1319 u8_t n;
1320 u8_t pcb_idx;
1321 struct dns_table_entry *entry = &dns_table[idx];
1322 const ip_addr_t *dst;
1323 ip_addr_t dns_server_addr;
1324 u16_t dst_port;
1325
1326 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
1327 (u16_t)(entry->server_idx), entry->name));
1328 LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
1329
1330 if (!DNS_SERVER_IS_AVAILABLE(entry, entry->server_idx)
1331 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
1332 && !entry->is_mdns
1333 #endif
1334 ) {
1335 /* DNS server not valid anymore, e.g. PPP netif has been shut down */
1336 /* call specified callback function if provided */
1337 dns_call_found(idx, NULL, 0);
1338 /* flush this entry */
1339 entry->retries = DNS_MAX_RETRIES - 1;
1340 return ERR_OK;
1341 }
1342
1343 // memory overflow (adding const and variable)
1344 if (strlen(entry->name) > DNS_MAX_NAME_LENGTH) {
1345 return ERR_MEM;
1346 }
1347
1348 /* if here, we have either a new query or a retry on a previous query to process */
1349 p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
1350 SIZEOF_DNS_QUERY), PBUF_RAM);
1351 if (p != NULL) {
1352
1353 /* fill dns header */
1354 memset(&hdr, 0, SIZEOF_DNS_HDR);
1355 hdr.id = lwip_htons(entry->txid);
1356 hdr.flags1 = DNS_FLAG1_RD;
1357 hdr.numquestions = PP_HTONS(1);
1358 pbuf_take(p, &hdr, SIZEOF_DNS_HDR);
1359 hostname = entry->name;
1360 --hostname;
1361
1362 /* convert hostname into suitable query format. */
1363 query_idx = SIZEOF_DNS_HDR;
1364 do {
1365 ++hostname;
1366 hostname_part = hostname;
1367 for (n = 0; *hostname != '.' && *hostname != 0; ++hostname, ++n) {
1368 }
1369 if (n > DNS_MAX_LABEL_LENGTH) {
1370 (void)pbuf_free(p);
1371 entry->state = DNS_STATE_UNUSED;
1372 return ERR_ARG;
1373 }
1374 copy_len = (u16_t)(hostname - hostname_part);
1375 if (query_idx + n + 1 > 0xFFFF) {
1376 /* u16_t overflow */
1377 goto overflow_return;
1378 }
1379 pbuf_put_at(p, query_idx, n);
1380 pbuf_take_at(p, hostname_part, copy_len, (u16_t)(query_idx + 1));
1381 query_idx = (u16_t)(query_idx + n + 1);
1382 } while (*hostname != 0);
1383 pbuf_put_at(p, query_idx, 0);
1384 query_idx++;
1385
1386 /* fill dns query */
1387 if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) {
1388 qry.type = PP_HTONS(DNS_RRTYPE_AAAA);
1389 } else {
1390 qry.type = PP_HTONS(DNS_RRTYPE_A);
1391 }
1392 qry.cls = PP_HTONS(DNS_RRCLASS_IN);
1393 pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx);
1394
1395 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1396 pcb_idx = entry->pcb_idx;
1397 #else
1398 pcb_idx = 0;
1399 #endif
1400 /* send dns packet */
1401 LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
1402 entry->txid, entry->name, entry->server_idx));
1403 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
1404 if (entry->is_mdns) {
1405 dst_port = DNS_MQUERY_PORT;
1406 #if LWIP_IPV6
1407 if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) {
1408 dst = &dns_mquery_v6group;
1409 }
1410 #endif
1411 #if LWIP_IPV4 && LWIP_IPV6
1412 else
1413 #endif
1414 #if LWIP_IPV4
1415 {
1416 dst = &dns_mquery_v4group;
1417 }
1418 #endif
1419 } else
1420 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
1421 {
1422 dst_port = DNS_SERVER_PORT;
1423 ip_addr_copy(dns_server_addr, dns_servers[entry->server_idx]);
1424
1425 #if LWIP_IPV4 && LWIP_IPV6
1426 /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
1427 if (IP_IS_V6_VAL(dns_server_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&dns_server_addr))) {
1428 unmap_ipv4_mapped_ipv6(ip_2_ip4(&dns_server_addr), ip_2_ip6(&dns_server_addr));
1429 IP_SET_TYPE_VAL(dns_server_addr, IPADDR_TYPE_V4);
1430 }
1431 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1432 dst = &dns_server_addr;
1433 }
1434 err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
1435
1436 /* free pbuf */
1437 pbuf_free(p);
1438 } else {
1439 err = ERR_MEM;
1440 }
1441
1442 return err;
1443 overflow_return:
1444 pbuf_free(p);
1445 return ERR_VAL;
1446 }
1447
1448 #if LWIP_DNS_REVERSE
1449 static err_t
reverse_dns_send(u8_t idx)1450 reverse_dns_send(u8_t idx)
1451 {
1452 err_t err;
1453 struct dns_hdr hdr;
1454 struct dns_query qry;
1455 struct pbuf *p = NULL;
1456 u16_t query_idx;
1457 u16_t copy_len;
1458 const char *encoded_domain = NULL;
1459 const char *encoded_domain_part = NULL;
1460 u8_t n;
1461 u8_t pcb_idx;
1462 struct reverse_dns_table_entry *entry = &reverse_dns_table[idx];
1463 const ip_addr_t *dst = NULL;
1464 ip_addr_t dns_server_addr;
1465 u16_t dst_port;
1466
1467 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
1468 (u16_t)(entry->server_idx), entry->encoded_ip.name));
1469
1470 LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
1471
1472 if (!DNS_SERVER_IS_AVAILABLE(entry, entry->server_idx)
1473 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
1474 && !entry->is_mdns
1475 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
1476 ) {
1477 /* DNS server not valid anymore, e.g. PPP netif has been shut down */
1478 /* call specified callback function if provided */
1479 reverse_dns_call_found(idx, NULL, 0);
1480 /* flush this entry */
1481 entry->retries = DNS_MAX_RETRIES - 1;
1482 return ERR_OK;
1483 }
1484
1485 /* if here, we have either a new query or a retry on a previous query to process */
1486 p = pbuf_alloc(PBUF_TRANSPORT,
1487 (u16_t)(SIZEOF_DNS_HDR + strlen((char *)(entry->encoded_ip.name)) +
1488 DNS_TYPE_LENGTH + SIZEOF_DNS_QUERY), PBUF_RAM);
1489 if (p == NULL) {
1490 return ERR_MEM;
1491 }
1492
1493 /* fill dns header */
1494 memset(&hdr, 0, SIZEOF_DNS_HDR);
1495 hdr.id = lwip_htons(entry->txid);
1496 hdr.flags1 = DNS_FLAG1_RD;
1497 hdr.numquestions = PP_HTONS(1);
1498 (void)pbuf_take(p, &hdr, SIZEOF_DNS_HDR);
1499 encoded_domain = (char *)(entry->encoded_ip.name);
1500 --encoded_domain;
1501
1502 /* convert hostname into suitable query format. */
1503 query_idx = SIZEOF_DNS_HDR;
1504 do {
1505 ++encoded_domain;
1506 encoded_domain_part = encoded_domain;
1507 for (n = 0; (*encoded_domain != '.') && (*encoded_domain != 0); ++encoded_domain, ++n) {
1508 }
1509 copy_len = (u16_t)(encoded_domain - encoded_domain_part);
1510 pbuf_put_at(p, query_idx, n);
1511 (void)pbuf_take_at(p, encoded_domain_part, copy_len, (u16_t)(query_idx + 1));
1512 query_idx = (u16_t)(query_idx + n + 1);
1513 } while (*encoded_domain != 0);
1514 pbuf_put_at(p, query_idx, 0);
1515 query_idx++;
1516
1517 /* fill dns query */
1518 qry.type = PP_HTONS(DNS_RRTYPE_PTR);
1519 qry.cls = PP_HTONS(DNS_RRCLASS_IN);
1520 (void)pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx);
1521
1522 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1523 pcb_idx = entry->pcb_idx;
1524 #else
1525 pcb_idx = 0;
1526 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
1527
1528 /* send dns packet */
1529 LWIP_DEBUGF(DNS_DEBUG, ("sending Reverse DNS request ID %d for name \"%s\" to server %d\r\n",
1530 entry->txid, entry->encoded_ip.name, entry->server_idx));
1531 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
1532 if (entry->is_mdns) {
1533 dst_port = DNS_MQUERY_PORT;
1534 } else
1535 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
1536 {
1537 dst_port = DNS_SERVER_PORT;
1538 ip_addr_copy(dns_server_addr, dns_servers[entry->server_idx]);
1539
1540 #if LWIP_IPV4 && LWIP_IPV6
1541 /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
1542 if (IP_IS_V6_VAL(dns_server_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&dns_server_addr))) {
1543 unmap_ipv4_mapped_ipv6(ip_2_ip4(&dns_server_addr), ip_2_ip6(&dns_server_addr));
1544 IP_SET_TYPE_VAL(dns_server_addr, IPADDR_TYPE_V4);
1545 }
1546 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1547 dst = &dns_server_addr;
1548 }
1549 err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
1550
1551 /* free pbuf */
1552 (void)pbuf_free(p);
1553
1554 return err;
1555 }
1556 #endif /* LWIP_DNS_REVERSE */
1557
1558 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1559 static struct udp_pcb *
dns_alloc_random_port(void)1560 dns_alloc_random_port(void)
1561 {
1562 err_t err;
1563 struct udp_pcb *pcb;
1564
1565 pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
1566 if (pcb == NULL) {
1567 /* out of memory, have to reuse an existing pcb */
1568 return NULL;
1569 }
1570 do {
1571 u16_t port = (u16_t)DNS_RAND_TXID();
1572 if (DNS_PORT_ALLOWED(port)) {
1573 err = udp_bind(pcb, IP_ANY_TYPE, port);
1574 } else {
1575 /* this port is not allowed, try again */
1576 err = ERR_USE;
1577 }
1578 } while (err == ERR_USE);
1579 if ((err != ERR_OK) && (err != ERR_USE)) {
1580 udp_remove(pcb);
1581 return NULL;
1582 }
1583 #if LWIP_SO_PRIORITY
1584 pcb->priority = LWIP_PKT_PRIORITY_DNS;
1585 #endif /* LWIP_SO_PRIORITY */
1586 udp_recv(pcb, dns_recv, NULL);
1587 return pcb;
1588 }
1589
1590 /**
1591 * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used
1592 * for sending a request
1593 *
1594 * @return an index into dns_pcbs
1595 */
1596 static u8_t
dns_alloc_pcb(void)1597 dns_alloc_pcb(void)
1598 {
1599 u8_t i;
1600 u8_t idx;
1601
1602 for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) {
1603 if (dns_pcbs[i] == NULL) {
1604 break;
1605 }
1606 }
1607 if (i < DNS_MAX_SOURCE_PORTS) {
1608 dns_pcbs[i] = dns_alloc_random_port();
1609 if (dns_pcbs[i] != NULL) {
1610 /* succeeded */
1611 dns_last_pcb_idx = i;
1612 return i;
1613 }
1614 }
1615 /* if we come here, creating a new UDP pcb failed, so we have to use
1616 an already existing one (so overflow is no issue) */
1617 idx = (u8_t)(dns_last_pcb_idx + 1);
1618 for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++, idx++) {
1619 if (idx >= DNS_MAX_SOURCE_PORTS) {
1620 idx = 0;
1621 }
1622 if (dns_pcbs[idx] != NULL) {
1623 dns_last_pcb_idx = idx;
1624 return idx;
1625 }
1626 }
1627 return DNS_MAX_SOURCE_PORTS;
1628 }
1629 #endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */
1630
1631 /**
1632 * dns_call_found() - call the found callback and check if there are duplicate
1633 * entries for the given hostname. If there are any, their found callback will
1634 * be called and they will be removed.
1635 *
1636 * @param idx dns table index of the entry that is resolved or removed
1637 * @param addr IP address for the hostname (or NULL on error or memory shortage)
1638 * @param ipaddr_count number of resolved IP address for hostname (or 0 on error or memory shortage)
1639 * If addr = NULL, then count will contain the error code which will be set to h_errno
1640 * If count contains error code, then it will be reset to zero after it is set to h_errno
1641 */
1642 static void
dns_call_found(u8_t idx,const ip_addr_t * addr,u32_t ipaddr_count)1643 dns_call_found(u8_t idx, const ip_addr_t *addr, u32_t ipaddr_count)
1644 {
1645 #if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0)
1646 u32_t i;
1647 #endif /* (LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0 */
1648
1649 #if LWIP_IPV4 && LWIP_IPV6
1650 if (addr != NULL) {
1651 /* check that address type matches the request and adapt the table entry */
1652 for (i = 0; i < ipaddr_count; ++i) {
1653 if (IP_IS_V6_VAL(addr[i])) {
1654 LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
1655 dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
1656 } else {
1657 LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
1658 dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
1659 }
1660 }
1661 }
1662 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1663
1664 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
1665 for (i = 0; i < DNS_MAX_REQUESTS; i++) {
1666 if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) {
1667 (*dns_requests[i].found)(dns_table[idx].name, addr, ipaddr_count, dns_requests[i].arg);
1668 /* flush this entry */
1669 dns_requests[i].found = NULL;
1670 }
1671 }
1672 #else
1673 if (dns_requests[idx].found) {
1674 (*dns_requests[idx].found)(dns_table[idx].name, addr, ipaddr_count, dns_requests[idx].arg);
1675 }
1676 dns_requests[idx].found = NULL;
1677 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0 */
1678 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1679 /* close the pcb used unless other request are using it */
1680 for (i = 0; i < DNS_MAX_REQUESTS; i++) {
1681 if (i == idx) {
1682 continue; /* only check other requests */
1683 }
1684 if (dns_table[i].state == DNS_STATE_ASKING) {
1685 if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) {
1686 /* another request is still using the same pcb */
1687 dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
1688 break;
1689 }
1690 }
1691 }
1692 if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) {
1693 /* if we come here, the pcb is not used any more and can be removed */
1694 udp_remove(dns_pcbs[dns_table[idx].pcb_idx]);
1695 dns_pcbs[dns_table[idx].pcb_idx] = NULL;
1696 dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
1697 }
1698 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
1699 }
1700
1701 #if LWIP_DNS_REVERSE
1702 static void
reverse_dns_call_found(u8_t idx,const char * hostname,u32_t name_count)1703 reverse_dns_call_found(u8_t idx, const char *hostname, u32_t name_count)
1704 {
1705 #if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0)
1706 u8_t i;
1707 #endif /* (LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0 */
1708
1709 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
1710 for (i = 0; i < DNS_MAX_REQUESTS; i++) {
1711 if (reverse_dns_requests[i].found && (reverse_dns_requests[i].reverse_dns_table_idx == idx)) {
1712 (*reverse_dns_requests[i].found)(hostname, name_count, reverse_dns_requests[i].arg);
1713 /* flush this entry */
1714 reverse_dns_requests[i].found = NULL;
1715 }
1716 }
1717 #else
1718 if (reverse_dns_requests[idx].found) {
1719 (*reverse_dns_requests[idx].found)(hostname, name_count, reverse_dns_requests[idx].arg);
1720 }
1721 reverse_dns_requests[idx].found = NULL;
1722 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0 */
1723
1724 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1725 /* close the pcb used unless other request are using it */
1726 for (i = 0; i < DNS_MAX_REQUESTS; i++) {
1727 if (i == idx) {
1728 continue; /* only check other requests */
1729 }
1730 if (reverse_dns_table[i].state == DNS_STATE_ASKING) {
1731 if (reverse_dns_table[i].pcb_idx == reverse_dns_table[idx].pcb_idx) {
1732 /* another request is still using the same pcb */
1733 reverse_dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
1734 break;
1735 }
1736 }
1737 }
1738 if (reverse_dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) {
1739 /* if we come here, the pcb is not used any more and can be removed */
1740 udp_remove(dns_pcbs[reverse_dns_table[idx].pcb_idx]);
1741 dns_pcbs[reverse_dns_table[idx].pcb_idx] = NULL;
1742 reverse_dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
1743 }
1744 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
1745 }
1746 #endif /* LWIP_DNS_REVERSE */
1747
1748 /* Create a query transmission ID that is unique for all outstanding queries */
1749 static u16_t
dns_create_txid(void)1750 dns_create_txid(void)
1751 {
1752 u16_t txid;
1753 u8_t i;
1754
1755 again:
1756 txid = (u16_t)DNS_RAND_TXID();
1757
1758 /* check whether the ID is unique */
1759 for (i = 0; i < DNS_TABLE_SIZE; i++) {
1760 if ((dns_table[i].state == DNS_STATE_ASKING) &&
1761 (dns_table[i].txid == txid)) {
1762 /* ID already used by another pending query */
1763 goto again;
1764 }
1765 }
1766
1767 return txid;
1768 }
1769
1770 /* Search for the first DNS server in server list */
1771 static void
dns_find_first_server(void)1772 dns_find_first_server(void)
1773 {
1774 u8_t i;
1775
1776 for (i = 0; i < DNS_MAX_SERVERS; i++) {
1777 if (!ip_addr_isany(&dns_servers[i])) {
1778 dns_first_server_idx = i;
1779 #if LWIP_DNS_REVERSE
1780 rdns_first_server_idx = i;
1781 #endif /* LWIP_DNS_REVERSE */
1782 return;
1783 }
1784 }
1785 /* if no valid dns server, should be processed in dns_gethostbyname and reverse_dns_getnamebyhost */
1786 /* server will be checked before send requests, so it's fine to return 0 */
1787 return;
1788 }
1789
1790 /**
1791 * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query.
1792 * Check an entry in the dns_table:
1793 * - send out query for new entries
1794 * - retry old pending entries on timeout (also with different servers)
1795 * - remove completed entries from the table if their TTL has expired
1796 *
1797 * @param i index of the dns_table entry to check
1798 */
1799 static err_t
dns_check_entry(u8_t i)1800 dns_check_entry(u8_t i)
1801 {
1802 err_t err = ERR_OK;
1803 struct dns_table_entry *entry = NULL;
1804 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
1805
1806 entry = &dns_table[i];
1807
1808 switch (entry->state) {
1809 case DNS_STATE_NEW:
1810 /* initialize new entry */
1811 entry->txid = dns_create_txid();
1812 entry->state = DNS_STATE_ASKING;
1813 entry->server_idx = dns_first_server_idx;
1814 entry->server_bitmap = 0;
1815 entry->tmr = 1;
1816 entry->retries = 0;
1817 entry->first_send_time = sys_now();
1818
1819 /* send DNS packet for this entry */
1820 err = dns_send(i);
1821 if (err != ERR_OK) {
1822 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
1823 ("dns_send returned error: %s\n", lwip_strerr(err)));
1824 }
1825 break;
1826 case DNS_STATE_ASKING:
1827 /* To ensure that the time gap between the force send routine and periodic send routine is atleast 100ms */
1828 if (sys_now() - (entry->first_send_time) <= 100) {
1829 /* If the gap is less than 100ms, then retransmit the DNS Query in the next tick */
1830 break;
1831 }
1832 if (--entry->tmr == 0) {
1833 if (dns_backupserver_available(entry, DNS_SERVER_SEARCHING_FLAG_SWITCH) == 0) {
1834 /* reset timer for next retry, linearly increasing as retries in each round */
1835 entry->tmr = entry->retries + 1;
1836
1837 /* send DNS packet for this entry */
1838 err = dns_send(i);
1839 if (err != ERR_OK) {
1840 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
1841 ("dns_send returned error: %s\n", lwip_strerr(err)));
1842 }
1843 } else {
1844 /* no available DNS server found */
1845 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name));
1846 /* call specified callback function if provided */
1847 dns_call_found(i, NULL, TRY_AGAIN);
1848 /* flush this entry */
1849 entry->state = DNS_STATE_UNUSED;
1850 break;
1851 }
1852 }
1853 break;
1854 case DNS_STATE_DONE:
1855 /* if the time to live is nul */
1856 if ((entry->ttl == 0) || (--entry->ttl == 0)) {
1857 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name));
1858 /* flush this entry, there cannot be any related pending entries in this state */
1859 entry->state = DNS_STATE_UNUSED;
1860 }
1861 break;
1862 case DNS_STATE_UNUSED:
1863 /* nothing to do */
1864 break;
1865 default:
1866 LWIP_ASSERT("unknown dns_table entry state:", 0);
1867 break;
1868 }
1869
1870 return err;
1871 }
1872
1873 #if LWIP_DNS_REVERSE
1874 static err_t
reverse_dns_check_entry(u8_t i)1875 reverse_dns_check_entry(u8_t i)
1876 {
1877 err_t err = ERR_OK;
1878 struct reverse_dns_table_entry *entry = NULL;
1879
1880 LWIP_ASSERT("reverse_dns_check_entry: array index out of bounds\n", i < DNS_TABLE_SIZE);
1881
1882 entry = &reverse_dns_table[i];
1883
1884 switch (entry->state) {
1885 case DNS_STATE_NEW:
1886 /* initialize new entry */
1887 entry->txid = dns_create_txid();
1888 entry->state = DNS_STATE_ASKING;
1889 entry->server_idx = rdns_first_server_idx;
1890 entry->server_bitmap = 0;
1891 entry->tmr = 1;
1892 entry->retries = 0;
1893 entry->first_send_time = sys_now();
1894
1895 /* send DNS packet for this entry */
1896 err = reverse_dns_send(i);
1897 if (err != ERR_OK) {
1898 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, ("reverse_dns_send returned error: %s\n", lwip_strerr(err)));
1899 }
1900 break;
1901 case DNS_STATE_ASKING:
1902 /* To ensure that the time gap between the force send routine and periodic send routine is atleast 100ms */
1903 if (sys_now() - (entry->first_send_time) <= 100) {
1904 /* If the gap is less than 100ms, then retransmit the DNS Query in the next tick */
1905 break;
1906 }
1907 if (--entry->tmr == 0) {
1908 if (reverse_dns_backupserver_available(entry, DNS_SERVER_SEARCHING_FLAG_SWITCH) == 0) {
1909 /* reset timer for next retry, linearly increasing as retries in each round */
1910 entry->tmr = entry->retries + 1;
1911
1912 /* send DNS packet for this entry */
1913 err = reverse_dns_send(i);
1914 if (err != ERR_OK) {
1915 LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
1916 ("reverse_dns_send returned error: %s\n", lwip_strerr(err)));
1917 }
1918 } else {
1919 /* no available DNS server found */
1920 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_check_entry: \"%s\": timeout\n", entry->encoded_ip.name));
1921 /* call specified callback function if provided */
1922 reverse_dns_call_found(i, NULL, TRY_AGAIN);
1923 /* flush this entry */
1924 entry->state = DNS_STATE_UNUSED;
1925 break;
1926 }
1927 }
1928 break;
1929 case DNS_STATE_DONE:
1930 /* if the time to live is null */
1931 if ((entry->ttl == 0) || (--entry->ttl == 0)) {
1932 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_check_entry: \"%s\": flush\n", entry->encoded_ip.name));
1933 /* flush this entry, there cannot be any related pending entries in this state */
1934 entry->state = DNS_STATE_UNUSED;
1935 }
1936 break;
1937 case DNS_STATE_UNUSED:
1938 /* nothing to do */
1939 break;
1940 default:
1941 LWIP_ASSERT("unknown reverse_dns_table entry state:", 0);
1942 break;
1943 }
1944
1945 return err;
1946 }
1947 #endif /* LWIP_DNS_REVERSE */
1948
1949 /**
1950 * Call dns_check_entry for each entry in dns_table - check all entries.
1951 */
1952 static void
dns_check_entries(void)1953 dns_check_entries(void)
1954 {
1955 u8_t i;
1956
1957 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1958 (void)dns_check_entry(i);
1959 }
1960 }
1961
1962 #if LWIP_DNS_REVERSE
1963 /**
1964 * Call dns_check_entry for each entry in dns_table - check all entries.
1965 */
1966 static void
reverse_dns_check_entries(void)1967 reverse_dns_check_entries(void)
1968 {
1969 u8_t i;
1970
1971 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1972 (void)reverse_dns_check_entry(i);
1973 }
1974 }
1975 #endif /* LWIP_DNS_REVERSE */
1976
1977 /**
1978 * Save TTL and call dns_call_found for correct response.
1979 */
1980 static void
dns_correct_response(u8_t idx,u32_t ttl)1981 dns_correct_response(u8_t idx, u32_t ttl)
1982 {
1983 struct dns_table_entry *entry = &dns_table[idx];
1984 entry->state = DNS_STATE_DONE;
1985
1986 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: response = \"%s\"\n", entry->name));
1987
1988 #ifdef LWIP_DEV_DEBUG
1989 u32_t j;
1990 for (j = 0; j < entry->ipaddr_count; j++) {
1991 ip_addr_debug_print_val(DNS_DEBUG, entry->ipaddr[j]);
1992 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
1993 }
1994 #endif /* LWIP_DEV_DEBUG */
1995
1996 /* read the answer resource record's TTL, and maximize it if needed */
1997 if (ttl > DNS_MAX_TTL) {
1998 ttl = DNS_MAX_TTL;
1999 }
2000 entry->ttl = ttl;
2001
2002 /* consider this server as the 'main' fDNS server, for query, try this first */
2003 if (dns_first_server_idx != entry->server_idx) {
2004 dns_first_server_idx = entry->server_idx;
2005 }
2006
2007 dns_call_found(idx, entry->ipaddr, entry->ipaddr_count);
2008
2009 if (entry->ttl == 0) {
2010 /* RFC 883, page 29: "Zero values are
2011 interpreted to mean that the RR can only be used for the
2012 transaction in progress, and should not be cached."
2013 -> flush this entry now */
2014 /* entry reused during callback? */
2015 if (entry->state == DNS_STATE_DONE) {
2016 entry->state = DNS_STATE_UNUSED;
2017 }
2018 }
2019 }
2020
2021 #if LWIP_DNS_REVERSE
2022 /**
2023 * Save TTL and call reverse_dns_call_found for correct response.
2024 */
2025 static void
reverse_dns_correct_response(u8_t idx,u32_t ttl)2026 reverse_dns_correct_response(u8_t idx, u32_t ttl)
2027 {
2028 struct reverse_dns_table_entry *entry = &reverse_dns_table[idx];
2029 entry->state = DNS_STATE_DONE;
2030
2031 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_correct_response: response = \"%s\"\n", entry->name));
2032
2033 /* read the answer resource record's TTL, and maximize it if needed */
2034 if (ttl > DNS_MAX_TTL) {
2035 ttl = DNS_MAX_TTL;
2036 }
2037 entry->ttl = ttl;
2038
2039 /* consider this server as the 'main' rDNS server, for next query, try this first */
2040 if (rdns_first_server_idx != entry->server_idx) {
2041 rdns_first_server_idx = entry->server_idx;
2042 }
2043
2044 reverse_dns_call_found(idx, entry->name, entry->name_count);
2045
2046 if (entry->ttl == 0) {
2047 /* RFC 883, page 29: "Zero values are
2048 interpreted to mean that the RR can only be used for the
2049 transaction in progress, and should not be cached."
2050 -> flush this entry now */
2051 /* entry reused during callback? */
2052 if (entry->state == DNS_STATE_DONE) {
2053 entry->state = DNS_STATE_UNUSED;
2054 }
2055 }
2056 }
2057 #endif /* LWIP_DNS_REVERSE */
2058
2059 /*
2060 * Check whether there are other backup DNS servers available to try
2061 * @param
2062 * - pentry: the forward dns_table entry to check.
2063 * - flags: Only support DNS_SERVER_SEARCHING_FLAG_SWITCH for now.
2064 * If DNS_SERVER_SEARCHING_FLAG_SWITCH set, switch to an available DNS server when searching.
2065 * Otherwise, only seach for an available DNS server without switching to it.
2066 * @Return value:
2067 * - 0: OK
2068 * - 1: NOK
2069 */
2070 static u8_t
dns_backupserver_available(struct dns_table_entry * pentry,u8_t flags)2071 dns_backupserver_available(struct dns_table_entry *pentry, u8_t flags)
2072 {
2073 u8_t idx, retries;
2074 u8_t j;
2075
2076 if (pentry != NULL) {
2077 idx = pentry->server_idx;
2078 retries = pentry->retries;
2079
2080 for (j = 0; j < DNS_MAX_SERVERS; j++) {
2081 idx = (idx + 1) % DNS_MAX_SERVERS;
2082 if (idx == dns_first_server_idx) {
2083 /* for the next round, increase retry times */
2084 retries++;
2085 }
2086 if (retries >= DNS_MAX_RETRIES) {
2087 /* return NOK if greater than limited retry times */
2088 return 1;
2089 }
2090
2091 if (DNS_SERVER_IS_AVAILABLE(pentry, idx)
2092 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2093 && !pentry->is_mdns
2094 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
2095 ) {
2096 if ((flags & DNS_SERVER_SEARCHING_FLAG_SWITCH) != 0) {
2097 /* if here, we need to update the information for this entry.
2098 in other failure cases, no need to do this because the request will stop. */
2099 pentry->server_idx = idx;
2100 pentry->retries = retries;
2101 }
2102 return 0;
2103 }
2104 }
2105 }
2106 return 1;
2107 }
2108
2109 #if LWIP_DNS_REVERSE
2110 /*
2111 * Check whether there are other backup reverse DNS servers available to try
2112 * @param
2113 * - rentry: the reverse dns_table entry to check.
2114 * - flags: Only support DNS_SERVER_SEARCHING_FLAG_SWITCH for now.
2115 * If DNS_SERVER_SEARCHING_FLAG_SWITCH set, switch to an available DNS server when searching.
2116 * Otherwise, only seach for an available DNS server without switching to it.
2117 * @Return value:
2118 * - 0: OK
2119 * - 1: NOK
2120 */
2121 static u8_t
reverse_dns_backupserver_available(struct reverse_dns_table_entry * rentry,u8_t flags)2122 reverse_dns_backupserver_available(struct reverse_dns_table_entry *rentry, u8_t flags)
2123 {
2124 u8_t idx, retries;
2125 u8_t j;
2126
2127 if (rentry != NULL) {
2128 idx = rentry->server_idx;
2129 retries = rentry->retries;
2130
2131 for (j = 0; j < DNS_MAX_SERVERS; j++) {
2132 idx = (idx + 1) % DNS_MAX_SERVERS;
2133 if (idx == rdns_first_server_idx) {
2134 /* for the next round, increase retry times */
2135 retries++;
2136 }
2137 if (retries >= DNS_MAX_RETRIES) {
2138 /* return NOK if greater than limited retry times */
2139 return 1;
2140 }
2141
2142 if (DNS_SERVER_IS_AVAILABLE(rentry, idx)
2143 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2144 && !rentry->is_mdns
2145 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
2146 ) {
2147 if ((flags & DNS_SERVER_SEARCHING_FLAG_SWITCH) != 0) {
2148 /* if here, we need to update the information for this entry.
2149 in other failure cases, no need to do this because the request will stop. */
2150 rentry->server_idx = idx;
2151 rentry->retries = retries;
2152 }
2153 return 0;
2154 }
2155 }
2156 }
2157 return 1;
2158 }
2159 #endif /* LWIP_DNS_REVERSE */
2160
2161 /**
2162 * Receive input function for DNS response packets arriving for the dns UDP pcb.
2163 * It multiplexes to process_forward_dns() and process_reverse_dns() based on the response txn id
2164 */
2165 static void
dns_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)2166 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
2167 {
2168 u8_t i;
2169 u16_t txid;
2170 struct dns_hdr hdr;
2171 struct dns_table_entry *forward_entry = NULL;
2172 #if LWIP_DNS_REVERSE
2173 struct reverse_dns_table_entry *reverse_entry = NULL;
2174 #endif /* LWIP_DNS_REVERSE */
2175
2176 LWIP_UNUSED_ARG(arg);
2177 LWIP_UNUSED_ARG(pcb);
2178 LWIP_UNUSED_ARG(port);
2179
2180 (void)memset_s(&hdr, sizeof(hdr), 0, sizeof(hdr));
2181
2182 /* is the dns message big enough ? */
2183 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) {
2184 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
2185 /* free pbuf and return */
2186 goto ignore_packet;
2187 }
2188
2189 /* copy dns payload inside static buffer for processing */
2190 if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) {
2191 /* Match the ID in the DNS header with the name table. */
2192 txid = lwip_htons(hdr.id);
2193 for (i = 0; i < DNS_TABLE_SIZE; i++) {
2194 forward_entry = &dns_table[i];
2195 #if LWIP_DNS_REVERSE
2196 reverse_entry = &reverse_dns_table[i];
2197 #endif /* LWIP_DNS_REVERSE */
2198 if ((forward_entry->state == DNS_STATE_ASKING) && (forward_entry->txid == txid)) {
2199 process_forward_dns(p, i, forward_entry, hdr, addr);
2200 break;
2201 }
2202 #if LWIP_DNS_REVERSE
2203 else if ((reverse_entry->state == DNS_STATE_ASKING) && (reverse_entry->txid == txid)) {
2204 process_reverse_dns(p, i, reverse_entry, hdr, addr);
2205 break;
2206 }
2207 #endif /* LWIP_DNS_REVERSE */
2208 }
2209 }
2210
2211 ignore_packet:
2212 /* deallocate memory and return */
2213 pbuf_free(p);
2214 return;
2215 }
2216
2217 /**
2218 * Queues a new hostname to resolve and sends out a DNS query for that hostname
2219 *
2220 * @param name the hostname that is to be queried
2221 * @param hostnamelen length of the hostname
2222 * @param found a callback function to be called on success, failure or timeout
2223 * @param callback_arg argument to pass to the callback function
2224 * @return err_t return code.
2225 */
2226 static err_t
dns_enqueue(const char * name,size_t hostnamelen,dns_found_callback found,void * callback_arg,u8_t dns_addrtype LWIP_DNS_ISMDNS_ARG (u8_t is_mdns))2227 dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
2228 void *callback_arg, u8_t dns_addrtype LWIP_DNS_ISMDNS_ARG(u8_t is_mdns))
2229 {
2230 u8_t i;
2231 u8_t lseq, lseqi;
2232 struct dns_table_entry *entry = NULL;
2233 size_t namelen;
2234 struct dns_req_entry *req;
2235 err_t err;
2236
2237 #if !LWIP_IPV6
2238 LWIP_UNUSED_ARG(dns_addrtype);
2239 #endif
2240
2241 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
2242 u8_t r;
2243 /* check for duplicate entries */
2244 for (i = 0; i < DNS_TABLE_SIZE; i++) {
2245 if ((dns_table[i].state == DNS_STATE_ASKING) &&
2246 (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) {
2247 #if LWIP_IPV4 && LWIP_IPV6
2248 if (dns_table[i].reqaddrtype != dns_addrtype) {
2249 /* requested address types don't match
2250 this can lead to 2 concurrent requests, but mixing the address types
2251 for the same host should not be that common */
2252 continue;
2253 }
2254 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2255 /* this is a duplicate entry, find a free request entry */
2256 for (r = 0; r < DNS_MAX_REQUESTS; r++) {
2257 if (dns_requests[r].found == 0) {
2258 dns_requests[r].found = found;
2259 dns_requests[r].arg = callback_arg;
2260 dns_requests[r].dns_table_idx = i;
2261 LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype);
2262 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name));
2263 return ERR_INPROGRESS;
2264 }
2265 }
2266 }
2267 }
2268 /* no duplicate entries found */
2269 #endif
2270
2271 /* search an unused entry, or the oldest one */
2272 lseq = 0;
2273 lseqi = DNS_TABLE_SIZE;
2274 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
2275 entry = &dns_table[i];
2276 /* is it an unused entry ? */
2277 if (entry->state == DNS_STATE_UNUSED) {
2278 break;
2279 }
2280 /* check if this is the oldest completed entry */
2281 if (entry->state == DNS_STATE_DONE) {
2282 u8_t age = (u8_t)(dns_seqno - entry->seqno);
2283 if (age > lseq) {
2284 lseq = age;
2285 lseqi = i;
2286 }
2287 }
2288 }
2289
2290 /* if we don't have found an unused entry, use the oldest completed one */
2291 if (i == DNS_TABLE_SIZE) {
2292 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
2293 /* no entry can be used now, table is full */
2294 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
2295 return ERR_MEM;
2296 } else {
2297 /* use the oldest completed one */
2298 i = lseqi;
2299 entry = &dns_table[i];
2300 }
2301 }
2302
2303 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
2304 /* find a free request entry */
2305 req = NULL;
2306 for (r = 0; r < DNS_MAX_REQUESTS; r++) {
2307 if (dns_requests[r].found == NULL) {
2308 req = &dns_requests[r];
2309 break;
2310 }
2311 }
2312 if (req == NULL) {
2313 /* no request entry can be used now, table is full */
2314 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name));
2315 return ERR_MEM;
2316 }
2317 req->dns_table_idx = i;
2318 #else
2319 /* in this configuration, the entry index is the same as the request index */
2320 req = &dns_requests[i];
2321 #endif
2322
2323 /* use this entry */
2324 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
2325
2326 /* fill the entry */
2327 entry->state = DNS_STATE_NEW;
2328 entry->seqno = dns_seqno;
2329 entry->ipaddr_count = 0;
2330 LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype);
2331 LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype);
2332 req->found = found;
2333 req->arg = callback_arg;
2334 namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH - 1);
2335 MEMCPY(entry->name, name, namelen);
2336 entry->name[namelen] = 0;
2337
2338 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
2339 entry->pcb_idx = dns_alloc_pcb();
2340 if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) {
2341 /* failed to get a UDP pcb */
2342 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name));
2343 entry->state = DNS_STATE_UNUSED;
2344 req->found = NULL;
2345 return ERR_MEM;
2346 }
2347 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
2348 #endif
2349
2350 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2351 entry->is_mdns = is_mdns;
2352 #endif
2353
2354 dns_seqno++;
2355
2356 /* force to send query without waiting timer */
2357 err = dns_check_entry(i);
2358
2359 /* dns query is enqueued */
2360 if (err == ERR_OK) {
2361 return ERR_INPROGRESS;
2362 } else {
2363 entry->state = DNS_STATE_UNUSED;
2364 req->found = NULL;
2365 return err;
2366 }
2367 }
2368
2369 #if LWIP_DNS_REVERSE
2370 static err_t
reverse_dns_enqueue(const struct reverse_domain * encoded_ip,reverse_dns_found_callback found,void * callback_arg)2371 reverse_dns_enqueue(const struct reverse_domain *encoded_ip, reverse_dns_found_callback found, void *callback_arg)
2372 {
2373 u8_t i;
2374 u8_t lseq, lseqi;
2375 struct reverse_dns_table_entry *entry = NULL;
2376 struct reverse_dns_req_entry *req = NULL;
2377 err_t err;
2378
2379 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
2380 u8_t r;
2381 /* check for duplicate entries */
2382 for (i = 0; i < DNS_TABLE_SIZE; i++) {
2383 if ((reverse_dns_table[i].state == DNS_STATE_ASKING) &&
2384 (lwip_strnicmp((const char*)(encoded_ip->name), (const char*)(reverse_dns_table[i].encoded_ip.name),
2385 sizeof(reverse_dns_table[i].encoded_ip.name)) == 0)) {
2386 /* this is a duplicate entry, find a free request entry */
2387 for (r = 0; r < DNS_MAX_REQUESTS; r++) {
2388 if (reverse_dns_requests[r].found == NULL) {
2389 reverse_dns_requests[r].found = found;
2390 reverse_dns_requests[r].arg = callback_arg;
2391 reverse_dns_requests[r].reverse_dns_table_idx = i;
2392 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": duplicate request\n", encoded_ip->name));
2393 return ERR_INPROGRESS;
2394 }
2395 }
2396 }
2397 }
2398 /* no duplicate entries found */
2399 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0 */
2400
2401 /* search an unused entry, or the oldest one */
2402 lseq = 0;
2403 lseqi = DNS_TABLE_SIZE;
2404 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
2405 entry = &reverse_dns_table[i];
2406 /* is it an unused entry ? */
2407 if (entry->state == DNS_STATE_UNUSED) {
2408 break;
2409 }
2410 /* check if this is the oldest completed entry */
2411 if (entry->state == DNS_STATE_DONE) {
2412 u8_t age = (u8_t)(dns_seqno - entry->seqno);
2413 if (age > lseq) {
2414 lseq = age;
2415 lseqi = i;
2416 }
2417 }
2418 }
2419
2420 /* if we don't have found an unused entry, use the oldest completed one */
2421 if (i == DNS_TABLE_SIZE) {
2422 if ((lseqi >= DNS_TABLE_SIZE) || (reverse_dns_table[lseqi].state != DNS_STATE_DONE)) {
2423 /* no entry can be used now, table is full */
2424 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": Reverse DNS entries table is full\n", encoded_ip->name));
2425 return ERR_MEM;
2426 } else {
2427 /* use the oldest completed one */
2428 i = lseqi;
2429 entry = &reverse_dns_table[i];
2430 }
2431 }
2432
2433 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
2434 /* find a free request entry */
2435 req = NULL;
2436 for (r = 0; r < DNS_MAX_REQUESTS; r++) {
2437 if (reverse_dns_requests[r].found == NULL) {
2438 req = &reverse_dns_requests[r];
2439 break;
2440 }
2441 }
2442 if (req == NULL) {
2443 /* no request entry can be used now, table is full */
2444 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": DNS request entries table is full\n", encoded_ip->name));
2445 return ERR_MEM;
2446 }
2447 req->reverse_dns_table_idx = i;
2448 #else
2449 /* in this configuration, the entry index is the same as the request index */
2450 req = &reverse_dns_requests[i];
2451 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0 */
2452
2453 /* use this entry */
2454 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", encoded_ip->name, (u16_t)(i)));
2455
2456 /* fill the entry */
2457 entry->state = DNS_STATE_NEW;
2458 entry->seqno = dns_seqno;
2459 entry->encoded_ip = *encoded_ip;
2460
2461 req->found = found;
2462 req->arg = callback_arg;
2463
2464 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
2465 entry->pcb_idx = dns_alloc_pcb();
2466 if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) {
2467 /* failed to get a UDP pcb */
2468 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": failed to allocate a pcb\n", encoded_ip->name));
2469 entry->state = DNS_STATE_UNUSED;
2470 req->found = NULL;
2471 return ERR_MEM;
2472 }
2473 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n",
2474 encoded_ip->name, (u16_t)(entry->pcb_idx)));
2475 #endif /* (LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0 */
2476
2477 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2478 entry->is_mdns = 0;
2479 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
2480
2481 dns_seqno++;
2482
2483 /* force to send query without waiting timer */
2484 err = reverse_dns_check_entry(i);
2485 /* dns query is enqueued */
2486 if (err == ERR_OK) {
2487 return ERR_INPROGRESS;
2488 } else {
2489 entry->state = DNS_STATE_UNUSED;
2490 req->found = NULL;
2491 return err;
2492 }
2493 }
2494 #endif /* LWIP_DNS_REVERSE */
2495
2496 /**
2497 * @ingroup dns
2498 * Resolve a hostname (string) into an IP address.
2499 * NON-BLOCKING callback version for use with raw API!!!
2500 *
2501 * Returns immediately with one of err_t return codes:
2502 * - ERR_OK if hostname is a valid IP address string or the host
2503 * name is already in the local names table.
2504 * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
2505 * for resolution if no errors are present.
2506 * - ERR_ARG: dns client not initialized or invalid hostname
2507 *
2508 * @param hostname the hostname that is to be queried
2509 * @param addr pointer to a ip_addr_t where to store the address if it is already
2510 * cached in the dns_table (only valid if ERR_OK is returned!)
2511 * @param count the number of resolved IP Address for hostname
2512 * @param found a callback function to be called on success, failure or timeout (only if
2513 * ERR_INPROGRESS is returned!)
2514 * @param callback_arg argument to pass to the callback function
2515 * @return a err_t return code.
2516 */
2517 err_t
dns_gethostbyname(const char * hostname,ip_addr_t * addr,u32_t * count,dns_found_callback found,void * callback_arg)2518 dns_gethostbyname(const char *hostname, ip_addr_t *addr, u32_t *count, dns_found_callback found,
2519 void *callback_arg)
2520 {
2521 return dns_gethostbyname_addrtype(hostname, addr, count, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT);
2522 }
2523
2524 /**
2525 * @ingroup dns
2526 * Like dns_gethostbyname, but returned address type can be controlled:
2527 * @param hostname the hostname that is to be queried
2528 * @param addr pointer to a ip_addr_t where to store the address if it is already
2529 * cached in the dns_table (only valid if ERR_OK is returned!)
2530 * @param found a callback function to be called on success, failure or timeout (only if
2531 * ERR_INPROGRESS is returned!)
2532 * @param callback_arg argument to pass to the callback function
2533 * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
2534 * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
2535 * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only
2536 * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only
2537 */
2538 err_t
dns_gethostbyname_addrtype(const char * hostname,ip_addr_t * addr,u32_t * count,dns_found_callback found,void * callback_arg,u8_t dns_addrtype)2539 dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, u32_t *count, dns_found_callback found,
2540 void *callback_arg, u8_t dns_addrtype)
2541 {
2542 size_t hostnamelen;
2543 int i = 0;
2544 int valid_dns_server = 0;
2545 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2546 u8_t is_mdns;
2547 #endif
2548 /* not initialized or no valid server yet, or invalid addr pointer
2549 * or invalid hostname or invalid hostname length */
2550 if ((addr == NULL) || (hostname == NULL) || (!hostname[0]) || (count == NULL) || (*count == 0)) {
2551 return ERR_ARG;
2552 }
2553 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
2554 if (dns_pcbs[0] == NULL) {
2555 return ERR_ARG;
2556 }
2557 #endif
2558 hostnamelen = strlen(hostname);
2559 if (hostnamelen >= DNS_MAX_NAME_LENGTH) {
2560 LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve"));
2561 return ERR_ARG;
2562 }
2563
2564 /* host name already in octet notation? set ip addr and return ERR_OK */
2565 if (ipaddr_aton(hostname, &addr[0])) {
2566 #if LWIP_IPV4 && LWIP_IPV6
2567 if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) ||
2568 (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6)))
2569 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2570 {
2571 *count = 1;
2572 return ERR_OK;
2573 }
2574 }
2575
2576 #if LWIP_HAVE_LOOPIF
2577 if (strcmp(hostname, "localhost") == 0) {
2578 ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), &addr[0]);
2579 *count = 1;
2580 return ERR_OK;
2581 }
2582 #endif /* LWIP_HAVE_LOOPIF */
2583
2584 for (i = 0; i < DNS_MAX_SERVERS; i++) {
2585 if (!ip_addr_isany_val(dns_servers[i])) {
2586 valid_dns_server = 1;
2587 break;
2588 }
2589 }
2590
2591 if (!valid_dns_server) {
2592 LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: There is no valid DNS server"));
2593 return ERR_CONN;
2594 }
2595
2596 /* already have this address cached? */
2597 if (dns_lookup(hostname, addr, count LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
2598 if (((IP_GET_TYPE(addr) == IPADDR_TYPE_V4) && (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6)) ||
2599 ((IP_GET_TYPE(addr) == IPADDR_TYPE_V6) && (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4))) {
2600 return ERR_VAL;
2601 }
2602 return ERR_OK;
2603 }
2604 #if LWIP_IPV4 && LWIP_IPV6
2605 if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
2606 /* fallback to 2nd IP type and try again to lookup */
2607 u8_t fallback;
2608 if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
2609 fallback = LWIP_DNS_ADDRTYPE_IPV6;
2610 } else {
2611 fallback = LWIP_DNS_ADDRTYPE_IPV4;
2612 }
2613 if (dns_lookup(hostname, addr, count LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) {
2614 return ERR_OK;
2615 }
2616 }
2617 #else /* LWIP_IPV4 && LWIP_IPV6 */
2618 LWIP_UNUSED_ARG(dns_addrtype);
2619 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2620
2621 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2622 if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) {
2623 is_mdns = 1;
2624 } else {
2625 is_mdns = 0;
2626 }
2627 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
2628
2629 *count = 0;
2630 /* queue query with specified callback */
2631 return dns_enqueue(hostname, hostnamelen, found, callback_arg, dns_addrtype LWIP_DNS_ISMDNS_ARG(is_mdns));
2632 }
2633
2634 #if LWIP_DNS_REVERSE
2635 err_t
reverse_dns_getnamebyhost(const ip_addr_t * ipaddr,char * hostname,reverse_dns_found_callback found,void * callback_arg)2636 reverse_dns_getnamebyhost(const ip_addr_t *ipaddr, char *hostname, reverse_dns_found_callback found,
2637 void *callback_arg)
2638 {
2639 int i;
2640 err_t err = 0;
2641 int valid_dns_server = 0;
2642 struct reverse_domain encoded_ip;
2643
2644 if ((ipaddr == NULL) || (hostname == NULL) || (found == NULL)) {
2645 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_getnamebyhost: Invalid parameters\n"));
2646 return ERR_ARG;
2647 }
2648
2649 if (!IP_IS_V4(ipaddr)
2650 #if LWIP_IPV6
2651 && !IP_IS_V6(ipaddr)
2652 #endif /* LWIP_IPV6 */
2653 ) {
2654 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_getnamebyhost: ipaddr not of a valid type\n"));
2655 return ERR_ARG;
2656 }
2657
2658 if (ip_addr_isloopback(ipaddr)) {
2659 if (strncpy_s(hostname, sizeof(LOCALHOST_STRING), LOCALHOST_STRING, sizeof(LOCALHOST_STRING)-1) != EOK) {
2660 return ERR_MEM;
2661 }
2662 return ERR_OK;
2663 }
2664
2665 for (i = 0; i < DNS_MAX_SERVERS; i++) {
2666 if (!ip_addr_isany_val(dns_servers[i])) {
2667 valid_dns_server = 1;
2668 break;
2669 }
2670 }
2671
2672 if (!valid_dns_server) {
2673 LWIP_DEBUGF(DNS_DEBUG, ("reverse_dns_getnamebyhost: There is no valid DNS server\n"));
2674 return ERR_CONN;
2675 }
2676
2677 if (IP_IS_V4(ipaddr)) {
2678 err = reverse_dns_build_reverse_v4_domain(&encoded_ip, (const ip4_addr_t*)ip_2_ip4(ipaddr));
2679 }
2680
2681 #if LWIP_IPV6
2682 if (IP_IS_V6(ipaddr)) {
2683 err = reverse_dns_build_reverse_v6_domain(&encoded_ip, (const ip6_addr_t*)ip_2_ip6(ipaddr));
2684 }
2685 #endif /* LWIP_IPV6 */
2686
2687 if (err != ERR_OK) {
2688 LWIP_DEBUGF(DNS_DEBUG,
2689 ("reverse_dns_getnamebyhost: Error during conversion from IP-Address to Reverse Domain Name\n"));
2690 return ERR_VAL;
2691 }
2692
2693 /* already have this IP cached? */
2694 if (reverse_dns_lookup(&encoded_ip, hostname) == ERR_OK) {
2695 return ERR_OK;
2696 }
2697
2698 return reverse_dns_enqueue(&encoded_ip, found, callback_arg);
2699 }
2700 #endif /* LWIP_DNS_REVERSE */
2701
2702 static
process_forward_dns(struct pbuf * p,u8_t entry_idx,struct dns_table_entry * entry,struct dns_hdr hdr,const ip_addr_t * addr)2703 void process_forward_dns(struct pbuf *p, u8_t entry_idx, struct dns_table_entry *entry, struct dns_hdr hdr,
2704 const ip_addr_t *addr)
2705 {
2706 struct dns_answer ans = {0};
2707 struct dns_query qry = {0};
2708 u8_t err_code = 0;
2709 u16_t res_idx;
2710 u16_t ret;
2711 u16_t nquestions, nanswers;
2712 ip_addr_t dns_server_addr;
2713
2714 entry->ipaddr_count = 0;
2715
2716 /* We only care about the question(s) and the answers. The authrr
2717 and the extrarr are simply discarded. */
2718 nquestions = lwip_htons(hdr.numquestions);
2719 nanswers = lwip_htons(hdr.numanswers);
2720
2721 /* Check for correct response. */
2722 if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) {
2723 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name));
2724 goto forward_dns_responseerr;
2725 }
2726
2727 if ((hdr.flags2 & DNS_FLAG2_ERR_MASK) != 0) {
2728 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name));
2729
2730 if ((hdr.flags2 & DNS_FLAG2_ERR_SERVER_FAILURE) != 0) {
2731 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": Some non-recoverable server failure occured\n", entry->name));
2732 err_code = NO_RECOVERY;
2733 } else if ((hdr.flags2 & DNS_FLAG2_ERR_NAME) != 0) {
2734 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": No such host name\n", entry->name));
2735 err_code = HOST_NOT_FOUND;
2736 }
2737
2738 goto forward_dns_responseerr;
2739 }
2740
2741 if (nquestions != 1) {
2742 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
2743 goto forward_dns_responseerr;
2744 }
2745
2746 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
2747 if (!entry->is_mdns)
2748 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
2749 {
2750 /* Check whether response comes from the same network address to which the
2751 question was sent. (RFC 5452) */
2752 ip_addr_copy(dns_server_addr, dns_servers[entry->server_idx]);
2753 #if LWIP_IPV4 && LWIP_IPV6
2754 /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
2755 if (IP_IS_V6_VAL(dns_server_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&dns_server_addr))) {
2756 unmap_ipv4_mapped_ipv6(ip_2_ip4(&dns_server_addr), ip_2_ip6(&dns_server_addr));
2757 IP_SET_TYPE_VAL(dns_server_addr, IPADDR_TYPE_V4);
2758 }
2759 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2760 if (!ip_addr_cmp(addr, &dns_server_addr)) {
2761 goto forward_dns_responseerr;
2762 }
2763 }
2764
2765 /* Check if the name in the "question" part match with the name in the entry and
2766 skip it if equal. */
2767 res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR, 1);
2768 if ((res_idx == 0xFFFF) || (res_idx == SIZEOF_DNS_HDR)) {
2769 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
2770 goto forward_dns_responseerr;
2771 }
2772
2773 /* check if "question" part matches the request */
2774 if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) {
2775 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
2776 goto forward_dns_responseerr;
2777 }
2778
2779 if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) ||
2780 (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) ||
2781 (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) {
2782 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
2783 goto forward_dns_responseerr;
2784 }
2785 /* skip the rest of the "question" part */
2786 res_idx = (u16_t)(res_idx + SIZEOF_DNS_QUERY);
2787
2788 if (nanswers == 0) {
2789 /* If there are no answers, then there is a chance to fallback based on entry->reqaddrtype */
2790 /* In that case, set err_code only if even the fallback response also has zero answers */
2791 if (!LWIP_DNS_ADDRTYPE_IS_FALLBACK(entry->reqaddrtype)) {
2792 LWIP_DEBUGF(DNS_DEBUG,
2793 ("dns_recv: \"%s\": Requested name is valid but there is no associated A / AAAA records with it\n",
2794 entry->name));
2795 err_code = NO_DATA;
2796 goto forward_dns_responseerr;
2797 }
2798 }
2799
2800 while ((nanswers > 0) && (res_idx < p->tot_len)) {
2801 res_idx = dns_skip_name(p, res_idx);
2802 if (res_idx == 0) {
2803 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Insufficient buffer length for parsing domain name\n"));
2804 goto forward_dns_responseerr;
2805 }
2806
2807 /* Check for IP address type and Internet class. Others are discarded. */
2808 if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) {
2809 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Parsing DNS answer failed\n"));
2810 goto forward_dns_responseerr;
2811 }
2812 if (res_idx + SIZEOF_DNS_ANSWER > 0xFFFF) {
2813 return;
2814 }
2815 res_idx = (u16_t)(res_idx + SIZEOF_DNS_ANSWER);
2816
2817 /* Only support a answer whose Internet class is 'the Internet' and IP address type is A or AAAA */
2818 if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) {
2819 #if LWIP_IPV4
2820 if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) {
2821 #if LWIP_IPV4 && LWIP_IPV6
2822 if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
2823 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2824 {
2825 /* keep the lowest ttl of multiple IP_add */
2826 if (lwip_ntohl(ans.ttl) < entry->ttl) {
2827 entry->ttl = lwip_ntohl(ans.ttl);
2828 }
2829
2830 /* read the IP address after answer resource record's header */
2831 ret = pbuf_copy_partial(p, &(entry->ipaddr[entry->ipaddr_count]), sizeof(ip4_addr_t), res_idx);
2832
2833 if (ret != sizeof(ip4_addr_t)) {
2834 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Parsing DNS answer failed\n"));
2835 goto forward_dns_responseerr;
2836 }
2837 if (ip4_addr_isany_val(*ip_2_ip4(&entry->ipaddr[entry->ipaddr_count])) ||
2838 ip4_addr_isnone_val(*ip_2_ip4(&entry->ipaddr[entry->ipaddr_count]))) {
2839 err_code = NO_DATA;
2840 goto forward_dns_responseerr;
2841 }
2842 IP_SET_TYPE(&(entry->ipaddr[entry->ipaddr_count]), IPADDR_TYPE_V4);
2843 entry->ipaddr_count++;
2844
2845 if (entry->ipaddr_count >= DNS_MAX_IPADDR) {
2846 break;
2847 }
2848 }
2849 }
2850 #endif /* LWIP_IPV4 */
2851 #if LWIP_IPV6
2852 if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) {
2853 #if LWIP_IPV4 && LWIP_IPV6
2854 if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
2855 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2856 {
2857 /* read the IP address after answer resource record's header */
2858 ret = pbuf_copy_partial(p, &(entry->ipaddr[entry->ipaddr_count]), sizeof(ip6_addr_t), res_idx);
2859
2860 if (ret != sizeof(ip6_addr_t)) {
2861 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Parsing DNS answer failed\n"));
2862 goto forward_dns_responseerr;
2863 }
2864 if (ip6_addr_isany_val(*ip_2_ip6(&(entry->ipaddr[entry->ipaddr_count]))) ||
2865 ip6_addr_isnone_val(*ip_2_ip6(&(entry->ipaddr[entry->ipaddr_count])))) {
2866 err_code = NO_DATA;
2867 goto forward_dns_responseerr;
2868 }
2869 IP_SET_TYPE(&(entry->ipaddr[entry->ipaddr_count]), IPADDR_TYPE_V6);
2870 entry->ipaddr_count++;
2871
2872 if (entry->ipaddr_count >= DNS_MAX_IPADDR) {
2873 break;
2874 }
2875 }
2876 }
2877 #endif /* LWIP_IPV6 */
2878 }
2879 /* skip this answer */
2880 if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) {
2881 goto forward_dns_responseerr;
2882 }
2883 res_idx = (u16_t)(res_idx + lwip_htons(ans.len));
2884 --nanswers;
2885 }
2886
2887 forward_dns_responseerr:
2888 if (entry->ipaddr_count) {
2889 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: response = \"%s\"\n", entry->name));
2890 #ifdef LWIP_DEV_DEBUG
2891 u16_t i;
2892 for (i = 0; i < entry->ipaddr_count; i++) {
2893 ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr[i])));
2894 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
2895 }
2896 #endif /* LWIP_DEV_DEBUG */
2897 dns_correct_response(entry_idx, lwip_ntohl(ans.ttl));
2898 } else {
2899 /* if no IP address extracted from response, mark this server as unavailable */
2900 DNS_SERVER_SET_UNAVAILABLE(entry, entry->server_idx);
2901
2902 if (dns_backupserver_available(entry, 0) == 0) {
2903 /* if there is another backup DNS server to try, then don't stop the DNS request */
2904 /* retry the next available server immediately */
2905 entry->tmr = 1;
2906 entry->state = DNS_STATE_ASKING;
2907 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": request the other server\n", entry->name));
2908 /* contact next available server for this entry */
2909 (void)dns_check_entry(entry_idx);
2910 return;
2911 }
2912
2913 #if LWIP_IPV4 && LWIP_IPV6
2914 if (LWIP_DNS_ADDRTYPE_IS_FALLBACK(entry->reqaddrtype)) {
2915 /* if no resolution and backup server is found, then check if there is scope for fallback */
2916 if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
2917 /* IPv4 failed, try IPv6 */
2918 dns_table[entry_idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
2919 } else {
2920 /* IPv6 failed, try IPv4 */
2921 dns_table[entry_idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
2922 }
2923 dns_table[entry_idx].state = DNS_STATE_NEW;
2924 (void)dns_check_entry(entry_idx);
2925 return;
2926 }
2927 #endif
2928
2929 /* ERROR: call specified callback function with NULL as name to indicate an error */
2930 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response with err_code = %d\n", entry->name, err_code));
2931 dns_call_found(entry_idx, NULL, err_code);
2932 /* flush this entry */
2933 dns_table[entry_idx].state = DNS_STATE_UNUSED;
2934 }
2935 }
2936
2937 #if LWIP_DNS_REVERSE
2938 static void
process_reverse_dns(struct pbuf * p,u8_t entry_idx,struct reverse_dns_table_entry * reverse_entry,struct dns_hdr hdr,const ip_addr_t * addr)2939 process_reverse_dns(struct pbuf *p, u8_t entry_idx, struct reverse_dns_table_entry *reverse_entry, struct dns_hdr hdr,
2940 const ip_addr_t *addr)
2941 {
2942 struct dns_answer ans = {0};
2943 struct dns_query qry = {0};
2944 ip_addr_t dns_server_addr;
2945 u16_t res_idx;
2946 u16_t ret;
2947 u16_t nquestions, nanswers;
2948 u16_t i;
2949 u8_t err_code = 0;
2950 u8_t length;
2951
2952 reverse_entry->name_count = 0;
2953
2954 /* We only care about the question(s) and the answers. The authrr
2955 and the extrarr are simply discarded. */
2956 nquestions = lwip_htons(hdr.numquestions);
2957 nanswers = lwip_htons(hdr.numanswers);
2958
2959 /* Check for correct response. */
2960 if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) {
2961 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", reverse_entry->encoded_ip.name));
2962 goto reverse_dns_responseerr;
2963 }
2964
2965 if ((hdr.flags2 & DNS_FLAG2_ERR_MASK) != 0) {
2966 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", reverse_entry->encoded_ip.name));
2967
2968 if ((hdr.flags2 & DNS_FLAG2_ERR_SERVER_FAILURE) != 0) {
2969 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": Some non-recoverable server failure occured\n",
2970 reverse_entry->encoded_ip.name));
2971 err_code = NO_RECOVERY;
2972 }
2973
2974 goto reverse_dns_responseerr;
2975 }
2976
2977 if (nquestions != 1) {
2978 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", reverse_entry->encoded_ip.name));
2979 goto reverse_dns_responseerr;
2980 }
2981
2982 /* Check whether response comes from the same network address to which the
2983 question was sent. (RFC 5452) */
2984 ip_addr_copy(dns_server_addr, dns_servers[reverse_entry->server_idx]);
2985 #if LWIP_IPV4 && LWIP_IPV6
2986 /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
2987 if (IP_IS_V6_VAL(dns_server_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&dns_server_addr))) {
2988 unmap_ipv4_mapped_ipv6(ip_2_ip4(&dns_server_addr), ip_2_ip6(&dns_server_addr));
2989 IP_SET_TYPE_VAL(dns_server_addr, IPADDR_TYPE_V4);
2990 }
2991 #endif /* LWIP_IPV4 && LWIP_IPV6 */
2992 if (!ip_addr_cmp(addr, &dns_server_addr)) {
2993 goto reverse_dns_responseerr;
2994 }
2995
2996 /* Check if the name in the "question" part match with the name in the entry and
2997 skip it if equal. */
2998 res_idx = dns_compare_name(reverse_entry->encoded_ip.name, p, SIZEOF_DNS_HDR, 1);
2999 if ((res_idx == 0xFFFF) || (res_idx == SIZEOF_DNS_HDR)) {
3000 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", reverse_entry->encoded_ip.name));
3001 goto reverse_dns_responseerr;
3002 }
3003
3004 /* check if "question" part matches the request */
3005 if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) {
3006 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", reverse_entry->encoded_ip.name));
3007 goto reverse_dns_responseerr;
3008 }
3009
3010 if (qry.type != PP_HTONS(DNS_RRTYPE_PTR)) {
3011 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to a reverse_dns query\n",
3012 reverse_entry->encoded_ip.name));
3013 goto reverse_dns_responseerr;
3014 }
3015
3016 /* skip the rest of the "question" part */
3017 res_idx = (u16_t)(res_idx + SIZEOF_DNS_QUERY);
3018
3019 while ((nanswers > 0) && (res_idx < p->tot_len)) {
3020 res_idx = dns_skip_name(p, res_idx);
3021 if (res_idx == 0) {
3022 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Insufficient buffer length for parsing domain name\n"));
3023 goto reverse_dns_responseerr;
3024 }
3025
3026 /* Check for IP address type and Internet class. Others are discarded. */
3027 if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) {
3028 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Parsing Reverse DNS answer failed\n"));
3029 goto reverse_dns_responseerr;
3030 }
3031
3032 res_idx = (u16_t)(res_idx + SIZEOF_DNS_ANSWER);
3033
3034 /* Only need an answer whose Internet class is 'the Internet' and type is 'domain name pointer' */
3035 if (ans.cls == PP_HTONS(DNS_RRCLASS_IN) && ans.type == PP_HTONS(DNS_RRTYPE_PTR)) {
3036 ret = pbuf_copy_partial(p, reverse_entry->name, NI_MAXHOST, res_idx);
3037 if (ret == 0) {
3038 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Parsing Reverse DNS answer failed\n"));
3039 goto reverse_dns_responseerr;
3040 }
3041
3042 /* Hostname received from the network will be of type [3]www[6]google[3]com\0 */
3043 /* Where [] contains the length of the next part */
3044 /* This has to be converted to www.google.com\0 */
3045 i = 0;
3046 while (reverse_entry->name[i] != '\0') {
3047 length = (u8_t)(reverse_entry->name[i++]);
3048 if (length > DNS_MAX_LABEL_LENGTH) {
3049 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: Malformed Reverse DNS answer received\n"));
3050 goto reverse_dns_responseerr;
3051 }
3052 while (length && reverse_entry->name[i] != '\0') {
3053 reverse_entry->name[i - 1] = reverse_entry->name[i];
3054 ++i;
3055 --length;
3056 }
3057 if (reverse_entry->name[i] != '\0') {
3058 /* Dont insert period if there arent any more characters in the hostname */
3059 reverse_entry->name[i - 1] = '.';
3060 }
3061 }
3062 if (i) {
3063 reverse_entry->name[i - 1] = '\0';
3064 }
3065 reverse_entry->name_count = 1;
3066 break;
3067 }
3068 /* skip this answer */
3069 if ((u32_t)(res_idx + lwip_htons(ans.len)) > 0xFFFFU) {
3070 goto reverse_dns_responseerr;
3071 }
3072 res_idx = (u16_t)(res_idx + lwip_htons(ans.len));
3073 --nanswers;
3074 }
3075
3076 reverse_dns_responseerr:
3077 if (reverse_entry->name_count) {
3078 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: response = \"%s\"\n", reverse_entry->name));
3079 reverse_dns_correct_response(entry_idx, lwip_ntohl(ans.ttl));
3080 } else {
3081 /* if no IP address extracted from response, mark this server as unavailable */
3082 DNS_SERVER_SET_UNAVAILABLE(reverse_entry, reverse_entry->server_idx);
3083
3084 if (reverse_dns_backupserver_available(reverse_entry, 0) == 0) {
3085 /* if there is another backup DNS server to try, then don't stop the DNS request */
3086 /* retry the next available server immediately */
3087 reverse_entry->tmr = 1;
3088 reverse_entry->state = DNS_STATE_ASKING;
3089 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": request the other server\n", reverse_entry->encoded_ip.name));
3090 /* contact next available server for this entry */
3091 (void)reverse_dns_check_entry(entry_idx);
3092 return;
3093 }
3094
3095 /* ERROR: call specified callback function with NULL as name to indicate an error */
3096 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", reverse_entry->encoded_ip.name));
3097 reverse_dns_call_found(entry_idx, NULL, err_code);
3098
3099 /* flush this entry */
3100 reverse_dns_table[entry_idx].state = DNS_STATE_UNUSED;
3101 }
3102 }
3103 #endif /* LWIP_DNS_REVERSE */
3104
3105 #endif /* LWIP_DNS */
3106
3107 #if defined(LWIP_DENY_DNS_SERVER) && (LWIP_DENY_DNS_SERVER)
3108 static struct udp_pcb *dns_server_pcb = NULL;
3109
3110 static void
dns_server_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)3111 dns_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
3112 {
3113 struct pbuf *send_p = NULL;
3114 struct dns_hdr send_hdr = {0};
3115
3116 LWIP_UNUSED_ARG(arg);
3117
3118 LWIP_DEBUGF(DNS_DEBUG, ("dns_server_recv::ip "));
3119 ip_addr_debug_print_val(DNS_DEBUG, *addr);
3120 LWIP_DEBUGF(DNS_DEBUG, ("port %d\r\n", port));
3121
3122 /* is the dns message big enough ? */
3123 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) {
3124 LWIP_DEBUGF(DNS_DEBUG, ("dns_server_recv: pbuf too small\n"));
3125 /* free pbuf and return */
3126 goto ignore_packet;
3127 }
3128
3129 if (pbuf_copy_partial(p, &send_hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) {
3130 /* set flags */
3131 send_hdr.flags1 |= DNS_FLAG1_RESPONSE;
3132 send_hdr.flags2 = DNS_FLAG2_REFUSE; /* Reply code (Query Refused) */
3133 }
3134
3135 send_p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(p->tot_len), PBUF_RAM);
3136 if (send_p != NULL) {
3137 memcpy_s(send_p->payload, p->tot_len, p->payload, p->tot_len);
3138 pbuf_take(send_p, &send_hdr, SIZEOF_DNS_HDR);
3139 } else {
3140 LWIP_DEBUGF(DNS_DEBUG, ("dns_server_recv: pbuf alloc fail\n"));
3141 goto ignore_packet;
3142 }
3143
3144 (void)udp_sendto(pcb, send_p, addr, port);
3145
3146 ignore_packet:
3147 /* deallocate memory and return */
3148 pbuf_free(p);
3149 return;
3150 }
3151
dns_server_init(void)3152 void dns_server_init(void)
3153 {
3154 LWIP_DEBUGF(DNS_DEBUG, ("dns_server_init: initializing\n"));
3155
3156 if (dns_server_pcb == NULL) {
3157 dns_server_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
3158 #if LWIP_SO_PRIORITY
3159 dns_server_pcb->priority = LWIP_PKT_PRIORITY_DNS;
3160 #endif /* LWIP_SO_PRIORITY */
3161 udp_bind(dns_server_pcb, IP_ANY_TYPE, DNS_SERVER_PORT);
3162 udp_recv(dns_server_pcb, dns_server_recv, NULL);
3163 }
3164 LWIP_DEBUGF(DNS_DEBUG, ("dns_server_init\r\n"));
3165 }
3166
dns_server_deinit(void)3167 void dns_server_deinit(void)
3168 {
3169 if (dns_server_pcb != NULL) {
3170 udp_remove(dns_server_pcb);
3171 dns_server_pcb = NULL;
3172 }
3173 }
3174 #endif /* defined(LWIP_DENY_DNS_SERVER) && (LWIP_DENY_DNS_SERVER) */