STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
dns.c
Go to the documentation of this file.
1 
64 /*-----------------------------------------------------------------------------
65  * RFC 1035 - Domain names - implementation and specification
66  * RFC 2181 - Clarifications to the DNS Specification
67  *----------------------------------------------------------------------------*/
68 
73 /*-----------------------------------------------------------------------------
74  * Includes
75  *----------------------------------------------------------------------------*/
76 
77 #include "lwip/opt.h"
78 
79 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
80 
81 #include "lwip/udp.h"
82 #include "lwip/mem.h"
83 #include "lwip/memp.h"
84 #include "lwip/dns.h"
85 
86 #include <string.h>
87 
89 #ifndef DNS_RAND_TXID
90 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0)
91 #define DNS_RAND_TXID LWIP_RAND
92 #else
93 static u16_t dns_txid;
94 #define DNS_RAND_TXID() (++dns_txid)
95 #endif
96 #endif
97 
99 #ifndef DNS_PORT_ALLOWED
100 #define DNS_PORT_ALLOWED(port) ((port) >= 1024)
101 #endif
102 
104 #ifndef DNS_SERVER_PORT
105 #define DNS_SERVER_PORT 53
106 #endif
107 
109 #ifndef DNS_MAX_RETRIES
110 #define DNS_MAX_RETRIES 4
111 #endif
112 
114 #ifndef DNS_MAX_TTL
115 #define DNS_MAX_TTL 604800
116 #endif
117 
118 /* The number of parallel requests (i.e. calls to dns_gethostbyname
119  * that cannot be answered from the DNS table.
120  * This is set to the table size by default.
121  */
122 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
123 #ifndef DNS_MAX_REQUESTS
124 #define DNS_MAX_REQUESTS DNS_TABLE_SIZE
125 #endif
126 #else
127 /* In this configuration, both arrays have to have the same size and are used
128  * like one entry (used/free) */
129 #define DNS_MAX_REQUESTS DNS_TABLE_SIZE
130 #endif
131 
132 /* The number of UDP source ports used in parallel */
133 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
134 #ifndef DNS_MAX_SOURCE_PORTS
135 #define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS
136 #endif
137 #else
138 #ifdef DNS_MAX_SOURCE_PORTS
139 #undef DNS_MAX_SOURCE_PORTS
140 #endif
141 #define DNS_MAX_SOURCE_PORTS 1
142 #endif
143 
144 #if LWIP_IPV4 && LWIP_IPV6
145 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6))
146 #define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t)))
147 #define LWIP_DNS_ADDRTYPE_ARG(x) , x
148 #define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x
149 #define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0)
150 #else
151 #if LWIP_IPV6
152 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1
153 #else
154 #define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0
155 #endif
156 #define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1
157 #define LWIP_DNS_ADDRTYPE_ARG(x)
158 #define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0
159 #define LWIP_DNS_SET_ADDRTYPE(x, y)
160 #endif /* LWIP_IPV4 && LWIP_IPV6 */
161 
163 #define DNS_RRTYPE_A 1 /* a host address */
164 #define DNS_RRTYPE_NS 2 /* an authoritative name server */
165 #define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */
166 #define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */
167 #define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */
168 #define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */
169 #define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */
170 #define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */
171 #define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */
172 #define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */
173 #define DNS_RRTYPE_WKS 11 /* a well known service description */
174 #define DNS_RRTYPE_PTR 12 /* a domain name pointer */
175 #define DNS_RRTYPE_HINFO 13 /* host information */
176 #define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */
177 #define DNS_RRTYPE_MX 15 /* mail exchange */
178 #define DNS_RRTYPE_TXT 16 /* text strings */
179 #define DNS_RRTYPE_AAAA 28 /* IPv6 address */
180 
182 #define DNS_RRCLASS_IN 1 /* the Internet */
183 #define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
184 #define DNS_RRCLASS_CH 3 /* the CHAOS class */
185 #define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
186 #define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
187 
188 /* DNS protocol flags */
189 #define DNS_FLAG1_RESPONSE 0x80
190 #define DNS_FLAG1_OPCODE_STATUS 0x10
191 #define DNS_FLAG1_OPCODE_INVERSE 0x08
192 #define DNS_FLAG1_OPCODE_STANDARD 0x00
193 #define DNS_FLAG1_AUTHORATIVE 0x04
194 #define DNS_FLAG1_TRUNC 0x02
195 #define DNS_FLAG1_RD 0x01
196 #define DNS_FLAG2_RA 0x80
197 #define DNS_FLAG2_ERR_MASK 0x0f
198 #define DNS_FLAG2_ERR_NONE 0x00
199 #define DNS_FLAG2_ERR_NAME 0x03
200 
201 /* DNS protocol states */
202 #define DNS_STATE_UNUSED 0
203 #define DNS_STATE_NEW 1
204 #define DNS_STATE_ASKING 2
205 #define DNS_STATE_DONE 3
206 
207 #ifdef PACK_STRUCT_USE_INCLUDES
208 # include "arch/bpstruct.h"
209 #endif
212 struct dns_hdr {
214  PACK_STRUCT_FLD_8(u8_t flags1);
215  PACK_STRUCT_FLD_8(u8_t flags2);
216  PACK_STRUCT_FIELD(u16_t numquestions);
217  PACK_STRUCT_FIELD(u16_t numanswers);
218  PACK_STRUCT_FIELD(u16_t numauthrr);
219  PACK_STRUCT_FIELD(u16_t numextrarr);
222 #ifdef PACK_STRUCT_USE_INCLUDES
223 # include "arch/epstruct.h"
224 #endif
225 #define SIZEOF_DNS_HDR 12
226 
229 struct dns_query {
230  /* DNS query record starts with either a domain name or a pointer
231  to a name already present somewhere in the packet. */
232  u16_t type;
233  u16_t cls;
234 };
235 #define SIZEOF_DNS_QUERY 4
236 
239 struct dns_answer {
240  /* DNS answer record starts with either a domain name or a pointer
241  to a name already present somewhere in the packet. */
242  u16_t type;
243  u16_t cls;
244  u32_t ttl;
245  u16_t len;
246 };
247 #define SIZEOF_DNS_ANSWER 10
248 /* maximum allowed size for the struct due to non-packed */
249 #define SIZEOF_DNS_ANSWER_ASSERT 12
250 
252 struct dns_table_entry {
253  u32_t ttl;
254  ip_addr_t ipaddr;
255  u16_t txid;
256  u8_t state;
257  u8_t server_idx;
258  u8_t tmr;
259  u8_t retries;
260  u8_t seqno;
261 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
262  u8_t pcb_idx;
263 #endif
264  char name[DNS_MAX_NAME_LENGTH];
265 #if LWIP_IPV4 && LWIP_IPV6
266  u8_t reqaddrtype;
267 #endif /* LWIP_IPV4 && LWIP_IPV6 */
268 };
269 
272 struct dns_req_entry {
273  /* pointer to callback on DNS query done */
274  dns_found_callback found;
275  /* argument passed to the callback function */
276  void *arg;
277 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
278  u8_t dns_table_idx;
279 #endif
280 #if LWIP_IPV4 && LWIP_IPV6
281  u8_t reqaddrtype;
282 #endif /* LWIP_IPV4 && LWIP_IPV6 */
283 };
284 
285 #if DNS_LOCAL_HOSTLIST
286 
287 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
288 
290 static struct local_hostlist_entry *local_hostlist_dynamic;
291 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
292 
295 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
296 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
297 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
298 
300 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
301 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
302 #endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
303 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
304  DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
305 
306 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
307 
308 static void dns_init_local(void);
309 #endif /* DNS_LOCAL_HOSTLIST */
310 
311 
312 /* forward declarations */
313 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
314 static void dns_check_entries(void);
315 static void dns_call_found(u8_t idx, ip_addr_t* addr);
316 
317 /*-----------------------------------------------------------------------------
318  * Globals
319  *----------------------------------------------------------------------------*/
320 
321 /* DNS variables */
322 static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS];
323 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
324 static u8_t dns_last_pcb_idx;
325 #endif
326 static u8_t dns_seqno;
327 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
328 static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS];
329 static ip_addr_t dns_servers[DNS_MAX_SERVERS];
330 
331 #ifndef LWIP_DNS_STRICMP
332 #define LWIP_DNS_STRICMP(str1, str2) dns_stricmp(str1, str2)
333 
336 static int
337 dns_stricmp(const char* str1, const char* str2)
338 {
339  char c1, c2;
340 
341  do {
342  c1 = *str1++;
343  c2 = *str2++;
344  if (c1 != c2) {
345  char c1_upc = c1 | 0x20;
346  if ((c1_upc >= 'a') && (c1_upc <= 'z')) {
347  /* characters are not equal an one is in the alphabet range:
348  downcase both chars and check again */
349  char c2_upc = c2 | 0x20;
350  if (c1_upc != c2_upc) {
351  /* still not equal */
352  /* don't care for < or > */
353  return 1;
354  }
355  } else {
356  /* characters are not equal but none is in the alphabet range */
357  return 1;
358  }
359  }
360  } while (c1 != 0);
361  return 0;
362 }
363 #endif /* LWIP_DNS_STRICMP */
364 
369 void
370 dns_init(void)
371 {
372 #ifdef DNS_SERVER_ADDRESS
373  /* initialize default DNS server address */
374  ip_addr_t dnsserver;
375  DNS_SERVER_ADDRESS(&dnsserver);
376  dns_setserver(0, &dnsserver);
377 #endif /* DNS_SERVER_ADDRESS */
378 
379  LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
380  sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
381  LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER",
382  sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT);
383 
384  LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
385 
386  /* if dns client not yet initialized... */
387 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
388  if (dns_pcbs[0] == NULL) {
389  dns_pcbs[0] = udp_new();
390  LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL);
391 
392  /* initialize DNS table not needed (initialized to zero since it is a
393  * global variable) */
394  LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
395  DNS_STATE_UNUSED == 0);
396 
397  /* initialize DNS client */
398  udp_bind(dns_pcbs[0], IP_ADDR_ANY, 0);
399  udp_recv(dns_pcbs[0], dns_recv, NULL);
400  }
401 #endif
402 
403 #if DNS_LOCAL_HOSTLIST
404  dns_init_local();
405 #endif
406 }
407 
414 void
415 dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
416 {
417  if (numdns < DNS_MAX_SERVERS) {
418  if (dnsserver != NULL) {
419  dns_servers[numdns] = (*dnsserver);
420  } else {
421  dns_servers[numdns] = *IP_ADDR_ANY;
422  }
423  }
424 }
425 
433 ip_addr_t
434 dns_getserver(u8_t numdns)
435 {
436  if (numdns < DNS_MAX_SERVERS) {
437  return dns_servers[numdns];
438  } else {
439  return *IP_ADDR_ANY;
440  }
441 }
442 
447 void
448 dns_tmr(void)
449 {
450  LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
451  dns_check_entries();
452 }
453 
454 #if DNS_LOCAL_HOSTLIST
455 static void
456 dns_init_local(void)
457 {
458 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
459  size_t i;
460  struct local_hostlist_entry *entry;
461  /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
462  struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
463  size_t namelen;
464  for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
465  struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
466  LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
467  namelen = strlen(init_entry->name);
468  LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
469  entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
470  LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
471  if (entry != NULL) {
472  char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry);
473  MEMCPY(entry_name, init_entry->name, namelen);
474  entry_name[namelen] = 0;
475  entry->name = entry_name;
476  entry->addr = init_entry->addr;
477  entry->next = local_hostlist_dynamic;
478  local_hostlist_dynamic = entry;
479  }
480  }
481 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
482 }
483 
492 static err_t
493 dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
494 {
495 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
496  struct local_hostlist_entry *entry = local_hostlist_dynamic;
497  while (entry != NULL) {
498  if ((LWIP_DNS_STRICMP(entry->name, hostname) == 0) &&
499  LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) {
500  if (addr) {
501  ip_addr_copy(*addr, entry->addr);
502  }
503  return ERR_OK;
504  }
505  entry = entry->next;
506  }
507 #else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
508  size_t i;
509  for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
510  if ((LWIP_DNS_STRICMP(local_hostlist_static[i].name, hostname) == 0) &&
511  LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) {
512  if (addr) {
513  ip_addr_copy(*addr, local_hostlist_static[i].addr);
514  }
515  return ERR_OK;
516  }
517  }
518 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
519  return ERR_ARG;
520 }
521 
522 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
523 
531 int
532 dns_local_removehost(const char *hostname, const ip_addr_t *addr)
533 {
534  int removed = 0;
535  struct local_hostlist_entry *entry = local_hostlist_dynamic;
536  struct local_hostlist_entry *last_entry = NULL;
537  while (entry != NULL) {
538  if (((hostname == NULL) || !LWIP_DNS_STRICMP(entry->name, hostname)) &&
539  ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
540  struct local_hostlist_entry *free_entry;
541  if (last_entry != NULL) {
542  last_entry->next = entry->next;
543  } else {
544  local_hostlist_dynamic = entry->next;
545  }
546  free_entry = entry;
547  entry = entry->next;
548  memp_free(MEMP_LOCALHOSTLIST, free_entry);
549  removed++;
550  } else {
551  last_entry = entry;
552  entry = entry->next;
553  }
554  }
555  return removed;
556 }
557 
566 err_t
567 dns_local_addhost(const char *hostname, const ip_addr_t *addr)
568 {
569  struct local_hostlist_entry *entry;
570  size_t namelen;
571  char* entry_name;
572  LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
573  namelen = strlen(hostname);
574  LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
575  entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
576  if (entry == NULL) {
577  return ERR_MEM;
578  }
579  entry_name = (char*)entry + sizeof(struct local_hostlist_entry);
580  MEMCPY(entry_name, hostname, namelen);
581  entry_name[namelen] = 0;
582  entry->name = entry_name;
583  ip_addr_copy(entry->addr, *addr);
584  entry->next = local_hostlist_dynamic;
585  local_hostlist_dynamic = entry;
586  return ERR_OK;
587 }
588 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
589 #endif /* DNS_LOCAL_HOSTLIST */
590 
605 static err_t
606 dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
607 {
608  u8_t i;
609 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
610 #endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
611 #if DNS_LOCAL_HOSTLIST
612  if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
613  return ERR_OK;
614  }
615 #endif /* DNS_LOCAL_HOSTLIST */
616 #ifdef DNS_LOOKUP_LOCAL_EXTERN
617  if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype))) {
618  return ERR_OK;
619  }
620 #endif /* DNS_LOOKUP_LOCAL_EXTERN */
621 
622  /* Walk through name list, return entry if found. If not, return NULL. */
623  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
624  if ((dns_table[i].state == DNS_STATE_DONE) &&
625  (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0) &&
626  LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) {
627  LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
628  ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
629  LWIP_DEBUGF(DNS_DEBUG, ("\n"));
630  if (addr) {
631  ip_addr_copy(*addr, dns_table[i].ipaddr);
632  }
633  return ERR_OK;
634  }
635  }
636 
637  return ERR_ARG;
638 }
639 
651 static u16_t
652 dns_compare_name(char *query, struct pbuf* p, u16_t start_offset)
653 {
654  unsigned char n;
655  u16_t response_offset = start_offset;
656 
657  do {
658  n = pbuf_get_at(p, response_offset++);
660  if ((n & 0xc0) == 0xc0) {
661  /* Compressed name: cannot be equal since we don't send them */
662  return 0xFFFF;
663  } else {
664  /* Not compressed name */
665  while (n > 0) {
666  if ((*query) != pbuf_get_at(p, response_offset)) {
667  return 0xFFFF;
668  }
669  ++response_offset;
670  ++query;
671  --n;
672  }
673  ++query;
674  }
675  } while (pbuf_get_at(p, response_offset) != 0);
676 
677  return response_offset + 1;
678 }
679 
687 static u16_t
688 dns_parse_name(struct pbuf* p, u16_t query_idx)
689 {
690  unsigned char n;
691 
692  do {
693  n = pbuf_get_at(p, query_idx++);
695  if ((n & 0xc0) == 0xc0) {
696  /* Compressed name */
697  break;
698  } else {
699  /* Not compressed name */
700  while (n > 0) {
701  ++query_idx;
702  --n;
703  }
704  }
705  } while (pbuf_get_at(p, query_idx) != 0);
706 
707  return query_idx + 1;
708 }
709 
716 static err_t
717 dns_send(u8_t idx)
718 {
719  err_t err;
720  struct dns_hdr hdr;
721  struct dns_query qry;
722  struct pbuf *p;
723  u16_t query_idx, copy_len;
724  const char *hostname, *hostname_part;
725  u8_t n;
726  u8_t pcb_idx;
727  struct dns_table_entry* entry = &dns_table[idx];
728 
729  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
730  (u16_t)(entry->server_idx), entry->name));
731  LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
732  if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
733  /* DNS server not valid anymore, e.g. PPP netif has been shut down */
734  /* call specified callback function if provided */
735  dns_call_found(idx, NULL);
736  /* flush this entry */
737  entry->state = DNS_STATE_UNUSED;
738  return ERR_OK;
739  }
740 
741  /* if here, we have either a new query or a retry on a previous query to process */
742  p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 +
743  SIZEOF_DNS_QUERY), PBUF_RAM);
744  if (p != NULL) {
745  /* fill dns header */
746  memset(&hdr, 0, SIZEOF_DNS_HDR);
747  hdr.id = htons(entry->txid);
748  hdr.flags1 = DNS_FLAG1_RD;
749  hdr.numquestions = PP_HTONS(1);
750  pbuf_take(p, &hdr, SIZEOF_DNS_HDR);
751  hostname = entry->name;
752  --hostname;
753 
754  /* convert hostname into suitable query format. */
755  query_idx = SIZEOF_DNS_HDR;
756  do {
757  ++hostname;
758  hostname_part = hostname;
759  for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) {
760  ++n;
761  }
762  copy_len = (u16_t)(hostname - hostname_part);
763  pbuf_put_at(p, query_idx, n);
764  pbuf_take_at(p, hostname_part, copy_len, query_idx + 1);
765  query_idx += n + 1;
766  } while (*hostname != 0);
767  pbuf_put_at(p, query_idx, 0);
768  query_idx++;
769 
770  /* fill dns query */
771  if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) {
772  qry.type = PP_HTONS(DNS_RRTYPE_AAAA);
773  } else {
774  qry.type = PP_HTONS(DNS_RRTYPE_A);
775  }
776  qry.cls = PP_HTONS(DNS_RRCLASS_IN);
777  pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx);
778 
779 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
780  pcb_idx = entry->pcb_idx;
781 #else
782  pcb_idx = 0;
783 #endif
784  /* send dns packet */
785  LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n",
786  entry->txid, entry->name, entry->server_idx));
787  err = udp_sendto(dns_pcbs[pcb_idx], p, &dns_servers[entry->server_idx], DNS_SERVER_PORT);
788 
789  /* free pbuf */
790  pbuf_free(p);
791  } else {
792  err = ERR_MEM;
793  }
794 
795  return err;
796 }
797 
798 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
799 static struct udp_pcb*
800 dns_alloc_random_port(void)
801 {
802  err_t err;
803  struct udp_pcb* ret;
804 
805  ret = udp_new();
806  if (ret == NULL) {
807  /* out of memory, have to reuse an existing pcb */
808  return NULL;
809  }
810  do {
811  u16_t port = (u16_t)DNS_RAND_TXID();
812  if (!DNS_PORT_ALLOWED(port)) {
813  /* this port is not allowed, try again */
814  err = ERR_USE;
815  continue;
816  }
817  err = udp_bind(ret, IP_ADDR_ANY, port);
818  } while (err == ERR_USE);
819  if (err != ERR_OK) {
820  udp_remove(ret);
821  return NULL;
822  }
823  udp_recv(ret, dns_recv, NULL);
824  return ret;
825 }
826 
833 static u8_t
834 dns_alloc_pcb(void)
835 {
836  u8_t i;
837  u8_t idx;
838 
839  for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) {
840  if (dns_pcbs[i] == NULL) {
841  break;
842  }
843  }
844  if (i < DNS_MAX_SOURCE_PORTS) {
845  dns_pcbs[i] = dns_alloc_random_port();
846  if (dns_pcbs[i] != NULL) {
847  /* succeeded */
848  dns_last_pcb_idx = i;
849  return i;
850  }
851  }
852  /* if we come here, creating a new UDP pcb failed, so we have to use
853  an already existing one */
854  for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) {
855  if (idx >= DNS_MAX_SOURCE_PORTS) {
856  idx = 0;
857  }
858  if (dns_pcbs[idx] != NULL) {
859  dns_last_pcb_idx = idx;
860  return idx;
861  }
862  }
863  return DNS_MAX_SOURCE_PORTS;
864 }
865 #endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */
866 
875 static void
876 dns_call_found(u8_t idx, ip_addr_t* addr)
877 {
878 #if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0)
879  u8_t i;
880 #endif
881 
882 #if LWIP_IPV4 && LWIP_IPV6
883  if (addr != NULL) {
884  /* check that address type matches the request and adapt the table entry */
885  if (IP_IS_V6_VAL(*addr)) {
886  LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
887  dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
888  } else {
889  LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype));
890  dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
891  }
892  }
893 #endif /* LWIP_IPV4 && LWIP_IPV6 */
894 
895 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
896  for (i = 0; i < DNS_MAX_REQUESTS; i++) {
897  if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) {
898  (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg);
899  /* flush this entry */
900  dns_requests[i].found = NULL;
901  }
902  }
903 #else
904  if (dns_requests[idx].found) {
905  (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg);
906  }
907  dns_requests[idx].found = NULL;
908 #endif
909 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
910  /* close the pcb used unless other request are using it */
911  for (i = 0; i < DNS_MAX_REQUESTS; i++) {
912  if (i == idx) {
913  continue; /* only check other requests */
914  }
915  if (dns_table[i].state == DNS_STATE_ASKING) {
916  if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) {
917  /* another request is still using the same pcb */
918  dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
919  break;
920  }
921  }
922  }
923  if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) {
924  /* if we come here, the pcb is not used any more and can be removed */
925  udp_remove(dns_pcbs[dns_table[idx].pcb_idx]);
926  dns_pcbs[dns_table[idx].pcb_idx] = NULL;
927  dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS;
928  }
929 #endif
930 }
931 
932 /* Create a query transmission ID that is unique for all outstanding queries */
933 static u16_t
934 dns_create_txid(void)
935 {
936  u16_t txid;
937  u8_t i;
938 
939 again:
940  txid = (u16_t)DNS_RAND_TXID();
941 
942  /* check whether the ID is unique */
943  for (i = 0; i < DNS_TABLE_SIZE; i++) {
944  if ((dns_table[i].state == DNS_STATE_ASKING) &&
945  (dns_table[i].txid == txid)) {
946  /* ID already used by another pending query */
947  goto again;
948  }
949  }
950 
951  return txid;
952 }
953 
963 static void
964 dns_check_entry(u8_t i)
965 {
966  err_t err;
967  struct dns_table_entry *entry = &dns_table[i];
968 
969  LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
970 
971  switch (entry->state) {
972 
973  case DNS_STATE_NEW: {
974  u16_t txid;
975  /* initialize new entry */
976  txid = dns_create_txid();
977  entry->txid = txid;
978  entry->state = DNS_STATE_ASKING;
979  entry->server_idx = 0;
980  entry->tmr = 1;
981  entry->retries = 0;
982 
983  /* send DNS packet for this entry */
984  err = dns_send(i);
985  if (err != ERR_OK) {
987  ("dns_send returned error: %s\n", lwip_strerr(err)));
988  }
989  break;
990  }
991 
992  case DNS_STATE_ASKING:
993  if (--entry->tmr == 0) {
994  if (++entry->retries == DNS_MAX_RETRIES) {
995  if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
996  /* change of server */
997  entry->server_idx++;
998  entry->tmr = 1;
999  entry->retries = 0;
1000  } else {
1001  LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name));
1002  /* call specified callback function if provided */
1003  dns_call_found(i, NULL);
1004  /* flush this entry */
1005  entry->state = DNS_STATE_UNUSED;
1006  break;
1007  }
1008  } else {
1009  /* wait longer for the next retry */
1010  entry->tmr = entry->retries;
1011  }
1012 
1013  /* send DNS packet for this entry */
1014  err = dns_send(i);
1015  if (err != ERR_OK) {
1017  ("dns_send returned error: %s\n", lwip_strerr(err)));
1018  }
1019  }
1020  break;
1021  case DNS_STATE_DONE:
1022  /* if the time to live is nul */
1023  if ((entry->ttl == 0) || (--entry->ttl == 0)) {
1024  LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name));
1025  /* flush this entry, there cannot be any related pending entries in this state */
1026  entry->state = DNS_STATE_UNUSED;
1027  }
1028  break;
1029  case DNS_STATE_UNUSED:
1030  /* nothing to do */
1031  break;
1032  default:
1033  LWIP_ASSERT("unknown dns_table entry state:", 0);
1034  break;
1035  }
1036 }
1037 
1041 static void
1042 dns_check_entries(void)
1043 {
1044  u8_t i;
1045 
1046  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1047  dns_check_entry(i);
1048  }
1049 }
1050 
1056 static void
1057 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
1058 {
1059  u8_t i, entry_idx = DNS_TABLE_SIZE;
1060  u16_t txid;
1061  u16_t res_idx;
1062  struct dns_hdr hdr;
1063  struct dns_answer ans;
1064  struct dns_query qry;
1065  u16_t nquestions, nanswers;
1066 
1067  LWIP_UNUSED_ARG(arg);
1068  LWIP_UNUSED_ARG(pcb);
1069  LWIP_UNUSED_ARG(port);
1070 
1071  /* is the dns message big enough ? */
1072  if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) {
1073  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
1074  /* free pbuf and return */
1075  goto memerr;
1076  }
1077 
1078  /* copy dns payload inside static buffer for processing */
1079  if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) {
1080  /* Match the ID in the DNS header with the name table. */
1081  txid = htons(hdr.id);
1082  for (i = 0; i < DNS_TABLE_SIZE; i++) {
1083  struct dns_table_entry *entry = &dns_table[i];
1084  entry_idx = i;
1085  if ((entry->state == DNS_STATE_ASKING) &&
1086  (entry->txid == txid)) {
1087  u8_t dns_err;
1088  /* This entry is now completed. */
1089  entry->state = DNS_STATE_DONE;
1090  dns_err = hdr.flags2 & DNS_FLAG2_ERR_MASK;
1091 
1092  /* We only care about the question(s) and the answers. The authrr
1093  and the extrarr are simply discarded. */
1094  nquestions = htons(hdr.numquestions);
1095  nanswers = htons(hdr.numanswers);
1096 
1097  /* Check for error. If so, call callback to inform. */
1098  if (((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) || (dns_err != 0) || (nquestions != 1)) {
1099  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name));
1100  /* call callback to indicate error, clean up memory and return */
1101  goto responseerr;
1102  }
1103 
1104  /* Check whether response comes from the same network address to which the
1105  question was sent. (RFC 5452) */
1106  if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
1107  /* call callback to indicate error, clean up memory and return */
1108  goto responseerr;
1109  }
1110 
1111  /* Check if the name in the "question" part match with the name in the entry and
1112  skip it if equal. */
1113  res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR);
1114  if (res_idx == 0xFFFF) {
1115  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
1116  /* call callback to indicate error, clean up memory and return */
1117  goto responseerr;
1118  }
1119 
1120  /* check if "question" part matches the request */
1121  pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx);
1122  if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) ||
1123  (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) ||
1124  (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) {
1125  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name));
1126  /* call callback to indicate error, clean up memory and return */
1127  goto responseerr;
1128  }
1129  /* skip the rest of the "question" part */
1130  res_idx += SIZEOF_DNS_QUERY;
1131 
1132  while ((nanswers > 0) && (res_idx < p->tot_len)) {
1133  /* skip answer resource record's host name */
1134  res_idx = dns_parse_name(p, res_idx);
1135 
1136  /* Check for IP address type and Internet class. Others are discarded. */
1137  pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx);
1138  if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) {
1139 #if LWIP_IPV4
1140  if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) {
1141 #if LWIP_IPV4 && LWIP_IPV6
1142  if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
1143 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1144  {
1145  ip4_addr_t ip4addr;
1146  res_idx += SIZEOF_DNS_ANSWER;
1147  /* read the answer resource record's TTL, and maximize it if needed */
1148  entry->ttl = ntohl(ans.ttl);
1149  if (entry->ttl > DNS_MAX_TTL) {
1150  entry->ttl = DNS_MAX_TTL;
1151  }
1152  /* read the IP address after answer resource record's header */
1153  pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx);
1154  ip_addr_copy_from_ip4(entry->ipaddr, ip4addr);
1155  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
1156  ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
1157  LWIP_DEBUGF(DNS_DEBUG, ("\n"));
1158  /* call specified callback function if provided */
1159  dns_call_found(entry_idx, &entry->ipaddr);
1160  if (entry->ttl == 0) {
1161  /* RFC 883, page 29: "Zero values are
1162  interpreted to mean that the RR can only be used for the
1163  transaction in progress, and should not be cached."
1164  -> flush this entry now */
1165  goto flushentry;
1166  }
1167  /* deallocate memory and return */
1168  goto memerr;
1169  }
1170  }
1171 #endif /* LWIP_IPV4 */
1172 #if LWIP_IPV6
1173  if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) {
1174 #if LWIP_IPV4 && LWIP_IPV6
1175  if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype))
1176 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1177  {
1178  ip6_addr_t ip6addr;
1179  res_idx += SIZEOF_DNS_ANSWER;
1180  /* read the answer resource record's TTL, and maximize it if needed */
1181  entry->ttl = ntohl(ans.ttl);
1182  if (entry->ttl > DNS_MAX_TTL) {
1183  entry->ttl = DNS_MAX_TTL;
1184  }
1185  /* read the IP address after answer resource record's header */
1186  pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx);
1187  ip_addr_copy_from_ip6(entry->ipaddr, ip6addr);
1188  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name));
1189  ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr)));
1190  LWIP_DEBUGF(DNS_DEBUG, (" AAAA\n"));
1191  /* call specified callback function if provided */
1192  dns_call_found(entry_idx, &entry->ipaddr);
1193  if (entry->ttl == 0) {
1194  /* RFC 883, page 29: "Zero values are
1195  interpreted to mean that the RR can only be used for the
1196  transaction in progress, and should not be cached."
1197  -> flush this entry now */
1198  goto flushentry;
1199  }
1200  /* deallocate memory and return */
1201  goto memerr;
1202  }
1203  }
1204 #endif /* LWIP_IPV6 */
1205  }
1206  /* skip this answer */
1207  res_idx += SIZEOF_DNS_ANSWER + htons(ans.len);
1208  --nanswers;
1209  }
1210 #if LWIP_IPV4 && LWIP_IPV6
1211  if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) ||
1212  (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
1213  if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
1214  /* IPv4 failed, try IPv6 */
1215  entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6;
1216  } else {
1217  /* IPv6 failed, try IPv4 */
1218  entry->reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4;
1219  }
1220  pbuf_free(p);
1221  entry->state = DNS_STATE_NEW;
1222  dns_check_entry(entry_idx);
1223  return;
1224  }
1225 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1226  LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name));
1227  /* call callback to indicate error, clean up memory and return */
1228  goto responseerr;
1229  }
1230  }
1231  }
1232 
1233  /* deallocate memory and return */
1234  goto memerr;
1235 
1236 responseerr:
1237  /* ERROR: call specified callback function with NULL as name to indicate an error */
1238  dns_call_found(entry_idx, NULL);
1239 flushentry:
1240  /* flush this entry */
1241  dns_table[entry_idx].state = DNS_STATE_UNUSED;
1242 
1243 memerr:
1244  /* free pbuf */
1245  pbuf_free(p);
1246  return;
1247 }
1248 
1258 static err_t
1259 dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found,
1260  void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype))
1261 {
1262  u8_t i;
1263  u8_t lseq, lseqi;
1264  struct dns_table_entry *entry = NULL;
1265  size_t namelen;
1266  struct dns_req_entry* req;
1267 
1268 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
1269  u8_t r;
1270  /* check for duplicate entries */
1271  for (i = 0; i < DNS_TABLE_SIZE; i++) {
1272  if ((dns_table[i].state == DNS_STATE_ASKING) &&
1273  (LWIP_DNS_STRICMP(name, dns_table[i].name) == 0)) {
1274 #if LWIP_IPV4 && LWIP_IPV6
1275  if (dns_table[i].reqaddrtype != dns_addrtype) {
1276  /* requested address types don't match
1277  this can lead to 2 concurrent requests, but mixing the address types
1278  for the same host should not be that common */
1279  continue;
1280  }
1281 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1282  /* this is a duplicate entry, find a free request entry */
1283  for (r = 0; r < DNS_MAX_REQUESTS; r++) {
1284  if (dns_requests[r].found == 0) {
1285  dns_requests[r].found = found;
1286  dns_requests[r].arg = callback_arg;
1287  dns_requests[r].dns_table_idx = i;
1288  LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype);
1289  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name));
1290  return ERR_INPROGRESS;
1291  }
1292  }
1293  }
1294  }
1295  /* no duplicate entries found */
1296 #endif
1297 
1298  /* search an unused entry, or the oldest one */
1299  lseq = 0;
1300  lseqi = DNS_TABLE_SIZE;
1301  for (i = 0; i < DNS_TABLE_SIZE; ++i) {
1302  entry = &dns_table[i];
1303  /* is it an unused entry ? */
1304  if (entry->state == DNS_STATE_UNUSED) {
1305  break;
1306  }
1307  /* check if this is the oldest completed entry */
1308  if (entry->state == DNS_STATE_DONE) {
1309  if ((u8_t)(dns_seqno - entry->seqno) > lseq) {
1310  lseq = dns_seqno - entry->seqno;
1311  lseqi = i;
1312  }
1313  }
1314  }
1315 
1316  /* if we don't have found an unused entry, use the oldest completed one */
1317  if (i == DNS_TABLE_SIZE) {
1318  if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
1319  /* no entry can be used now, table is full */
1320  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
1321  return ERR_MEM;
1322  } else {
1323  /* use the oldest completed one */
1324  i = lseqi;
1325  entry = &dns_table[i];
1326  }
1327  }
1328 
1329 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0)
1330  /* find a free request entry */
1331  req = NULL;
1332  for (r = 0; r < DNS_MAX_REQUESTS; r++) {
1333  if (dns_requests[r].found == NULL) {
1334  req = &dns_requests[r];
1335  break;
1336  }
1337  }
1338  if (req == NULL) {
1339  /* no request entry can be used now, table is full */
1340  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name));
1341  return ERR_MEM;
1342  }
1343  req->dns_table_idx = i;
1344 #else
1345  /* in this configuration, the entry index is the same as the request index */
1346  req = &dns_requests[i];
1347 #endif
1348 
1349  /* use this entry */
1350  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
1351 
1352  /* fill the entry */
1353  entry->state = DNS_STATE_NEW;
1354  entry->seqno = dns_seqno;
1355  LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype);
1356  LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype);
1357  req->found = found;
1358  req->arg = callback_arg;
1359  namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1);
1360  MEMCPY(entry->name, name, namelen);
1361  entry->name[namelen] = 0;
1362 
1363 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0)
1364  entry->pcb_idx = dns_alloc_pcb();
1365  if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) {
1366  /* failed to get a UDP pcb */
1367  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name));
1368  entry->state = DNS_STATE_UNUSED;
1369  req->found = NULL;
1370  return ERR_MEM;
1371  }
1372  LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx)));
1373 #endif
1374 
1375  dns_seqno++;
1376 
1377  /* force to send query without waiting timer */
1378  dns_check_entry(i);
1379 
1380  /* dns query is enqueued */
1381  return ERR_INPROGRESS;
1382 }
1383 
1403 err_t
1404 dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
1405  void *callback_arg)
1406 {
1407  return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT);
1408 }
1409 
1416 err_t
1417 dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found,
1418  void *callback_arg, u8_t dns_addrtype)
1419 {
1420  size_t hostnamelen;
1421  /* not initialized or no valid server yet, or invalid addr pointer
1422  * or invalid hostname or invalid hostname length */
1423  if ((addr == NULL) ||
1424  (!hostname) || (!hostname[0])) {
1425  return ERR_ARG;
1426  }
1427 #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0)
1428  if (dns_pcbs[0] == NULL) {
1429  return ERR_ARG;
1430  }
1431 #endif
1432  hostnamelen = strlen(hostname);
1433  if (hostnamelen >= DNS_MAX_NAME_LENGTH) {
1434  LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve"));
1435  return ERR_ARG;
1436  }
1437 
1438 
1439 #if LWIP_HAVE_LOOPIF
1440  if (strcmp(hostname, "localhost") == 0) {
1441  ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr);
1442  return ERR_OK;
1443  }
1444 #endif /* LWIP_HAVE_LOOPIF */
1445 
1446  /* host name already in octet notation? set ip addr and return ERR_OK */
1447  if (ipaddr_aton(hostname, addr)) {
1448 #if LWIP_IPV4 && LWIP_IPV6
1449  if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) ||
1450  (!IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6)))
1451 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1452  {
1453  return ERR_OK;
1454  }
1455  }
1456  /* already have this address cached? */
1457  if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) {
1458  return ERR_OK;
1459  }
1460 #if LWIP_IPV4 && LWIP_IPV6
1461  if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
1462  /* fallback to 2nd IP type and try again to lookup */
1463  u8_t fallback;
1464  if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) {
1465  fallback = LWIP_DNS_ADDRTYPE_IPV6;
1466  } else {
1467  fallback = LWIP_DNS_ADDRTYPE_IPV4;
1468  }
1469  if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) {
1470  return ERR_OK;
1471  }
1472  }
1473 #else /* LWIP_IPV4 && LWIP_IPV6 */
1474  LWIP_UNUSED_ARG(dns_addrtype);
1475 #endif /* LWIP_IPV4 && LWIP_IPV6 */
1476 
1477  /* queue query with specified callback */
1478  return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype));
1479 }
1480 
1481 #endif /* LWIP_DNS */
1482 
#define DNS_TABLE_SIZE
Definition: opt.h:883
#define DNS_MAX_NAME_LENGTH
Definition: opt.h:888
#define ERR_USE
Definition: err.h:60
#define PACK_STRUCT_STRUCT
Definition: arch.h:68
uint32_t idx
Definition: lcd_log.c:247
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define U16_F
Definition: cc.h:48
#define ip_addr_isany_val(ipaddr)
Definition: ip_addr.h:216
void pbuf_put_at(struct pbuf *p, u16_t offset, u8_t data)
Definition: pbuf.c:1239
#define PACK_STRUCT_FLD_8(x)
Definition: arch.h:78
#define htons(x)
Definition: def.h:86
#define MEMCPY(dst, src, len)
Definition: opt.h:84
#define PACK_STRUCT_FIELD(x)
Definition: arch.h:72
void memp_free(memp_t type, void *mem)
Definition: memp.c:399
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:199
Definition: pbuf.h:77
#define DNS_DEBUG
Definition: opt.h:2992
#define lwip_strerr(x)
Definition: err.h:79
#define LWIP_MIN(x, y)
Definition: def.h:50
#define IP_IS_V6(ipaddr)
Definition: ip_addr.h:197
#define DNS_MAX_SERVERS
Definition: opt.h:896
#define NULL
Definition: usbd_def.h:53
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:652
#define ntohl(x)
Definition: def.h:89
#define PP_HTONS(x)
Definition: def.h:97
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:203
unsigned long u32_t
Definition: cc.h:42
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
Definition: pbuf.c:1075
#define ERR_OK
Definition: err.h:52
u16_t tot_len
Definition: pbuf.h:122
#define IP_IS_V6_VAL(ipaddr)
Definition: ip_addr.h:196
Definition: pbuf.h:108
s8_t err_t
Definition: err.h:47
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:214
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
#define ip_addr_debug_print(debug, ipaddr)
Definition: ip_addr.h:221
#define ipaddr_aton(cp, addr)
Definition: ip_addr.h:225
#define PACK_STRUCT_BEGIN
Definition: arch.h:60
#define ip_addr_copy_from_ip6(dest, src)
Definition: ip_addr.h:204
#define ERR_ARG
Definition: err.h:71
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:952
u8_t pbuf_get_at(struct pbuf *p, u16_t offset)
Definition: pbuf.c:1219
unsigned char u8_t
Definition: cc.h:38
ip6_addr_t ip_addr_t
Definition: ip_addr.h:194
#define PACK_STRUCT_END
Definition: arch.h:64
#define ip_addr_set_loopback(is_ipv6, ipaddr)
Definition: ip_addr.h:210
#define ERR_INPROGRESS
Definition: err.h:57
void * memp_malloc(memp_t type)
Definition: memp.c:303
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1117
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:113
#define ERR_MEM
Definition: err.h:53
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:89
unsigned short u16_t
Definition: cc.h:40