87 #ifndef DNS_SERVER_ADDRESS
88 #define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222")))
92 #ifndef DNS_SERVER_PORT
93 #define DNS_SERVER_PORT 53
97 #ifndef DNS_MAX_RETRIES
98 #define DNS_MAX_RETRIES 4
103 #define DNS_MAX_TTL 604800
107 #define DNS_FLAG1_RESPONSE 0x80
108 #define DNS_FLAG1_OPCODE_STATUS 0x10
109 #define DNS_FLAG1_OPCODE_INVERSE 0x08
110 #define DNS_FLAG1_OPCODE_STANDARD 0x00
111 #define DNS_FLAG1_AUTHORATIVE 0x04
112 #define DNS_FLAG1_TRUNC 0x02
113 #define DNS_FLAG1_RD 0x01
114 #define DNS_FLAG2_RA 0x80
115 #define DNS_FLAG2_ERR_MASK 0x0f
116 #define DNS_FLAG2_ERR_NONE 0x00
117 #define DNS_FLAG2_ERR_NAME 0x03
120 #define DNS_STATE_UNUSED 0
121 #define DNS_STATE_NEW 1
122 #define DNS_STATE_ASKING 2
123 #define DNS_STATE_DONE 3
125 #ifdef PACK_STRUCT_USE_INCLUDES
126 # include "arch/bpstruct.h"
140 #ifdef PACK_STRUCT_USE_INCLUDES
141 # include "arch/epstruct.h"
143 #define SIZEOF_DNS_HDR 12
153 #define SIZEOF_DNS_QUERY 4
165 #define SIZEOF_DNS_ANSWER 10
168 struct dns_table_entry {
179 dns_found_callback found;
183 #if DNS_LOCAL_HOSTLIST
185 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
188 static struct local_hostlist_entry *local_hostlist_dynamic;
193 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
194 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
198 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
199 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
201 DNS_LOCAL_HOSTLIST_STORAGE_PRE
struct local_hostlist_entry local_hostlist_static[]
202 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
206 static void dns_init_local();
211 static void dns_recv(
void *s,
struct udp_pcb *pcb,
struct pbuf *p,
ip_addr_t *addr,
u16_t port);
212 static void dns_check_entries(
void);
219 static struct udp_pcb *dns_pcb;
220 static u8_t dns_seqno;
225 static u8_t* dns_payload;
239 DNS_SERVER_ADDRESS(&dnsserver);
244 if (dns_pcb ==
NULL) {
247 if (dns_pcb !=
NULL) {
250 LWIP_ASSERT(
"For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
251 DNS_STATE_UNUSED == 0);
255 udp_recv(dns_pcb, dns_recv,
NULL);
258 dns_setserver(0, &dnsserver);
261 #if DNS_LOCAL_HOSTLIST
277 dns_servers[numdns] = (*dnsserver);
289 dns_getserver(
u8_t numdns)
292 return dns_servers[numdns];
305 if (dns_pcb !=
NULL) {
311 #if DNS_LOCAL_HOSTLIST
315 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
317 struct local_hostlist_entry *entry;
319 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
321 for (i = 0; i <
sizeof(local_hostlist_init) /
sizeof(
struct local_hostlist_entry); i++) {
322 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
324 namelen = strlen(init_entry->name);
325 LWIP_ASSERT(
"namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
326 entry = (
struct local_hostlist_entry *)
memp_malloc(MEMP_LOCALHOSTLIST);
329 entry->name = (
char*)entry +
sizeof(
struct local_hostlist_entry);
330 MEMCPY((
char*)entry->name, init_entry->name, namelen);
331 ((
char*)entry->name)[namelen] = 0;
332 entry->addr = init_entry->addr;
333 entry->next = local_hostlist_dynamic;
334 local_hostlist_dynamic = entry;
348 dns_lookup_local(
const char *hostname)
350 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
351 struct local_hostlist_entry *entry = local_hostlist_dynamic;
352 while(entry !=
NULL) {
353 if(strcmp(entry->name, hostname) == 0) {
360 for (i = 0; i <
sizeof(local_hostlist_static) /
sizeof(
struct local_hostlist_entry); i++) {
361 if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
369 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
379 dns_local_removehost(
const char *hostname,
const ip_addr_t *addr)
382 struct local_hostlist_entry *entry = local_hostlist_dynamic;
383 struct local_hostlist_entry *last_entry =
NULL;
384 while (entry !=
NULL) {
385 if (((hostname ==
NULL) || !strcmp(entry->name, hostname)) &&
387 struct local_hostlist_entry *free_entry;
388 if (last_entry !=
NULL) {
389 last_entry->next = entry->next;
391 local_hostlist_dynamic = entry->next;
395 memp_free(MEMP_LOCALHOSTLIST, free_entry);
414 dns_local_addhost(
const char *hostname,
const ip_addr_t *addr)
416 struct local_hostlist_entry *entry;
419 namelen = strlen(hostname);
420 LWIP_ASSERT(
"namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
421 entry = (
struct local_hostlist_entry *)
memp_malloc(MEMP_LOCALHOSTLIST);
425 entry->name = (
char*)entry +
sizeof(
struct local_hostlist_entry);
426 MEMCPY((
char*)entry->name, hostname, namelen);
427 ((
char*)entry->name)[namelen] = 0;
429 entry->next = local_hostlist_dynamic;
430 local_hostlist_dynamic = entry;
450 dns_lookup(
const char *name)
453 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
456 #if DNS_LOCAL_HOSTLIST
457 if ((addr = dns_lookup_local(name)) !=
IPADDR_NONE) {
461 #ifdef DNS_LOOKUP_LOCAL_EXTERN
462 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) !=
IPADDR_NONE) {
469 if ((dns_table[i].state == DNS_STATE_DONE) &&
470 (strcmp(name, dns_table[i].name) == 0)) {
481 #if DNS_DOES_NAME_CHECK
493 dns_compare_name(
unsigned char *query,
unsigned char *response)
500 if ((n & 0xc0) == 0xc0) {
506 if ((*query) != (*response)) {
515 }
while (*response != 0);
527 static unsigned char *
528 dns_parse_name(
unsigned char *query)
535 if ((n & 0xc0) == 0xc0) {
545 }
while (*query != 0);
560 dns_send(
u8_t numdns,
const char* name,
u8_t id)
564 struct dns_query qry;
567 const char *pHostname;
571 (
u16_t)(numdns), name));
581 hdr = (
struct dns_hdr*)p->
payload;
582 memset(hdr, 0, SIZEOF_DNS_HDR);
584 hdr->flags1 = DNS_FLAG1_RD;
586 query = (
char*)hdr + SIZEOF_DNS_HDR;
595 for(n = 0; *pHostname !=
'.' && *pHostname != 0; ++pHostname) {
601 }
while(*pHostname != 0);
607 SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
613 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
615 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
636 dns_check_entry(
u8_t i)
639 struct dns_table_entry *pEntry = &dns_table[i];
641 LWIP_ASSERT(
"array index out of bounds", i < DNS_TABLE_SIZE);
643 switch(pEntry->state) {
645 case DNS_STATE_NEW: {
647 pEntry->state = DNS_STATE_ASKING;
653 err = dns_send(pEntry->numdns, pEntry->name, i);
656 (
"dns_send returned error: %s\n",
lwip_strerr(err)));
661 case DNS_STATE_ASKING: {
662 if (--pEntry->tmr == 0) {
663 if (++pEntry->retries == DNS_MAX_RETRIES) {
674 (*pEntry->found)(pEntry->name,
NULL, pEntry->arg);
676 pEntry->state = DNS_STATE_UNUSED;
677 pEntry->found =
NULL;
683 pEntry->tmr = pEntry->retries;
686 err = dns_send(pEntry->numdns, pEntry->name, i);
689 (
"dns_send returned error: %s\n",
lwip_strerr(err)));
695 case DNS_STATE_DONE: {
697 if (--pEntry->ttl == 0) {
700 pEntry->state = DNS_STATE_UNUSED;
701 pEntry->found =
NULL;
705 case DNS_STATE_UNUSED:
718 dns_check_entries(
void)
738 struct dns_answer ans;
739 struct dns_table_entry *pEntry;
740 u16_t nquestions, nanswers;
755 if (p->
tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
764 hdr = (
struct dns_hdr*)dns_payload;
766 if (i < DNS_TABLE_SIZE) {
767 pEntry = &dns_table[i];
768 if(pEntry->state == DNS_STATE_ASKING) {
770 pEntry->state = DNS_STATE_DONE;
771 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
775 nquestions =
htons(hdr->numquestions);
776 nanswers =
htons(hdr->numanswers);
779 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
785 #if DNS_DOES_NAME_CHECK
787 if (dns_compare_name((
unsigned char *)(pEntry->name), (
unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
795 pHostname = (
char *) dns_parse_name((
unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
797 while (nanswers > 0) {
799 pHostname = (
char *) dns_parse_name((
unsigned char *)pHostname);
802 SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
803 if((ans.type ==
PP_HTONS(DNS_RRTYPE_A)) && (ans.cls ==
PP_HTONS(DNS_RRCLASS_IN)) &&
806 pEntry->ttl =
ntohl(ans.ttl);
807 if (pEntry->ttl > DNS_MAX_TTL) {
808 pEntry->ttl = DNS_MAX_TTL;
811 SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER),
sizeof(
ip_addr_t));
817 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
822 pHostname = pHostname + SIZEOF_DNS_ANSWER +
htons(ans.len);
839 (*pEntry->found)(pEntry->name,
NULL, pEntry->arg);
842 pEntry->state = DNS_STATE_UNUSED;
843 pEntry->found =
NULL;
860 dns_enqueue(
const char *name, dns_found_callback found,
void *callback_arg)
864 struct dns_table_entry *pEntry =
NULL;
870 pEntry = &dns_table[i];
872 if (pEntry->state == DNS_STATE_UNUSED)
876 if (pEntry->state == DNS_STATE_DONE) {
877 if ((dns_seqno - pEntry->seqno) > lseq) {
878 lseq = dns_seqno - pEntry->seqno;
885 if (i == DNS_TABLE_SIZE) {
886 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
893 pEntry = &dns_table[i];
901 pEntry->state = DNS_STATE_NEW;
902 pEntry->seqno = dns_seqno++;
903 pEntry->found = found;
904 pEntry->arg = callback_arg;
906 MEMCPY(pEntry->name, name, namelen);
907 pEntry->name[namelen] = 0;
936 dns_gethostbyname(
const char *hostname,
ip_addr_t *addr, dns_found_callback found,
942 if ((dns_pcb ==
NULL) || (addr ==
NULL) ||
943 (!hostname) || (!hostname[0]) ||
949 if (strcmp(hostname,
"localhost")==0) {
959 ipaddr = dns_lookup(hostname);
967 return dns_enqueue(hostname, found, callback_arg);