ReactOS 0.4.15-dev-8393-g61b7fb9
dns.c
Go to the documentation of this file.
1
62/*-----------------------------------------------------------------------------
63 * RFC 1035 - Domain names - implementation and specification
64 * RFC 2181 - Clarifications to the DNS Specification
65 *----------------------------------------------------------------------------*/
66
71/*-----------------------------------------------------------------------------
72 * Includes
73 *----------------------------------------------------------------------------*/
74
75#include "lwip/opt.h"
76
77#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
78
79#include "lwip/udp.h"
80#include "lwip/mem.h"
81#include "lwip/memp.h"
82#include "lwip/dns.h"
83
84#include <string.h>
85
87#ifndef DNS_SERVER_ADDRESS
88#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
89#endif
90
92#ifndef DNS_SERVER_PORT
93#define DNS_SERVER_PORT 53
94#endif
95
97#ifndef DNS_MAX_RETRIES
98#define DNS_MAX_RETRIES 4
99#endif
100
102#ifndef DNS_MAX_TTL
103#define DNS_MAX_TTL 604800
104#endif
105
106/* DNS protocol flags */
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
118
119/* DNS protocol states */
120#define DNS_STATE_UNUSED 0
121#define DNS_STATE_NEW 1
122#define DNS_STATE_ASKING 2
123#define DNS_STATE_DONE 3
124
125#ifdef PACK_STRUCT_USE_INCLUDES
126# include "arch/bpstruct.h"
127#endif
130struct dns_hdr {
132 PACK_STRUCT_FIELD(u8_t flags1);
133 PACK_STRUCT_FIELD(u8_t flags2);
134 PACK_STRUCT_FIELD(u16_t numquestions);
135 PACK_STRUCT_FIELD(u16_t numanswers);
136 PACK_STRUCT_FIELD(u16_t numauthrr);
137 PACK_STRUCT_FIELD(u16_t numextrarr);
140#ifdef PACK_STRUCT_USE_INCLUDES
141# include "arch/epstruct.h"
142#endif
143#define SIZEOF_DNS_HDR 12
144
147struct dns_query {
148 /* DNS query record starts with either a domain name or a pointer
149 to a name already present somewhere in the packet. */
150 u16_t type;
151 u16_t cls;
152};
153#define SIZEOF_DNS_QUERY 4
154
157struct dns_answer {
158 /* DNS answer record starts with either a domain name or a pointer
159 to a name already present somewhere in the packet. */
160 u16_t type;
161 u16_t cls;
162 u32_t ttl;
163 u16_t len;
164};
165#define SIZEOF_DNS_ANSWER 10
166
168struct dns_table_entry {
169 u8_t state;
170 u8_t numdns;
171 u8_t tmr;
172 u8_t retries;
173 u8_t seqno;
174 u8_t err;
175 u32_t ttl;
177 ip_addr_t ipaddr;
178 /* pointer to callback on DNS query done */
179 dns_found_callback found;
180 void *arg;
181};
182
183#if DNS_LOCAL_HOSTLIST
184
185#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
188static struct local_hostlist_entry *local_hostlist_dynamic;
189#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
190
193#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
194#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
195#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
198#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
199#define DNS_LOCAL_HOSTLIST_STORAGE_POST
200#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
201DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
202 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
203
204#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
205
206static void dns_init_local();
207#endif /* DNS_LOCAL_HOSTLIST */
208
209
210/* forward declarations */
211static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
212static void dns_check_entries(void);
213
214/*-----------------------------------------------------------------------------
215 * Globales
216 *----------------------------------------------------------------------------*/
217
218/* DNS variables */
219static struct udp_pcb *dns_pcb;
220static u8_t dns_seqno;
221static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
222static ip_addr_t dns_servers[DNS_MAX_SERVERS];
224static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
225static u8_t* dns_payload;
226
231void
232dns_init()
233{
234 ip_addr_t dnsserver;
235
236 dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
237
238 /* initialize default DNS server address */
239 DNS_SERVER_ADDRESS(&dnsserver);
240
241 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
242
243 /* if dns client not yet initialized... */
244 if (dns_pcb == NULL) {
245 dns_pcb = udp_new();
246
247 if (dns_pcb != NULL) {
248 /* initialize DNS table not needed (initialized to zero since it is a
249 * global variable) */
250 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
251 DNS_STATE_UNUSED == 0);
252
253 /* initialize DNS client */
254 udp_bind(dns_pcb, IP_ADDR_ANY, 0);
255 udp_recv(dns_pcb, dns_recv, NULL);
256
257 /* initialize default DNS primary server */
258 dns_setserver(0, &dnsserver);
259 }
260 }
261#if DNS_LOCAL_HOSTLIST
262 dns_init_local();
263#endif
264}
265
272void
273dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
274{
275 if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
276 (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
277 dns_servers[numdns] = (*dnsserver);
278 }
279}
280
289dns_getserver(u8_t numdns)
290{
291 if (numdns < DNS_MAX_SERVERS) {
292 return dns_servers[numdns];
293 } else {
294 return *IP_ADDR_ANY;
295 }
296}
297
302void
303dns_tmr(void)
304{
305 if (dns_pcb != NULL) {
306 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
307 dns_check_entries();
308 }
309}
310
311#if DNS_LOCAL_HOSTLIST
312static void
313dns_init_local()
314{
315#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
316 int i;
317 struct local_hostlist_entry *entry;
318 /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
319 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
320 size_t namelen;
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];
323 LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
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);
327 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
328 if (entry != NULL) {
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;
335 }
336 }
337#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
338}
339
347static u32_t
348dns_lookup_local(const char *hostname)
349{
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) {
354 return ip4_addr_get_u32(&entry->addr);
355 }
356 entry = entry->next;
357 }
358#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
359 int i;
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) {
362 return ip4_addr_get_u32(&local_hostlist_static[i].addr);
363 }
364 }
365#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
366 return IPADDR_NONE;
367}
368
369#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
378int
379dns_local_removehost(const char *hostname, const ip_addr_t *addr)
380{
381 int removed = 0;
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)) &&
386 ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
387 struct local_hostlist_entry *free_entry;
388 if (last_entry != NULL) {
389 last_entry->next = entry->next;
390 } else {
391 local_hostlist_dynamic = entry->next;
392 }
393 free_entry = entry;
394 entry = entry->next;
395 memp_free(MEMP_LOCALHOSTLIST, free_entry);
396 removed++;
397 } else {
398 last_entry = entry;
399 entry = entry->next;
400 }
401 }
402 return removed;
403}
404
413err_t
414dns_local_addhost(const char *hostname, const ip_addr_t *addr)
415{
416 struct local_hostlist_entry *entry;
417 size_t namelen;
418 LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
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);
422 if (entry == NULL) {
423 return ERR_MEM;
424 }
425 entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
426 MEMCPY((char*)entry->name, hostname, namelen);
427 ((char*)entry->name)[namelen] = 0;
428 ip_addr_copy(entry->addr, *addr);
429 entry->next = local_hostlist_dynamic;
430 local_hostlist_dynamic = entry;
431 return ERR_OK;
432}
433#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
434#endif /* DNS_LOCAL_HOSTLIST */
435
449static u32_t
450dns_lookup(const char *name)
451{
452 u8_t i;
453#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
454 u32_t addr;
455#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
456#if DNS_LOCAL_HOSTLIST
457 if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
458 return addr;
459 }
460#endif /* DNS_LOCAL_HOSTLIST */
461#ifdef DNS_LOOKUP_LOCAL_EXTERN
462 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
463 return addr;
464 }
465#endif /* DNS_LOOKUP_LOCAL_EXTERN */
466
467 /* Walk through name list, return entry if found. If not, return NULL. */
468 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
469 if ((dns_table[i].state == DNS_STATE_DONE) &&
470 (strcmp(name, dns_table[i].name) == 0)) {
471 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
472 ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
473 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
474 return ip4_addr_get_u32(&dns_table[i].ipaddr);
475 }
476 }
477
478 return IPADDR_NONE;
479}
480
481#if DNS_DOES_NAME_CHECK
492static u8_t
493dns_compare_name(unsigned char *query, unsigned char *response)
494{
495 unsigned char n;
496
497 do {
498 n = *response++;
500 if ((n & 0xc0) == 0xc0) {
501 /* Compressed name */
502 break;
503 } else {
504 /* Not compressed name */
505 while (n > 0) {
506 if ((*query) != (*response)) {
507 return 1;
508 }
509 ++response;
510 ++query;
511 --n;
512 };
513 ++query;
514 }
515 } while (*response != 0);
516
517 return 0;
518}
519#endif /* DNS_DOES_NAME_CHECK */
520
527static unsigned char *
528dns_parse_name(unsigned char *query)
529{
530 unsigned char n;
531
532 do {
533 n = *query++;
535 if ((n & 0xc0) == 0xc0) {
536 /* Compressed name */
537 break;
538 } else {
539 /* Not compressed name */
540 while (n > 0) {
541 ++query;
542 --n;
543 };
544 }
545 } while (*query != 0);
546
547 return query + 1;
548}
549
559static err_t
560dns_send(u8_t numdns, const char* name, u8_t id)
561{
562 err_t err;
563 struct dns_hdr *hdr;
564 struct dns_query qry;
565 struct pbuf *p;
566 char *query, *nptr;
567 const char *pHostname;
568 u8_t n;
569
570 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
571 (u16_t)(numdns), name));
572 LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
573 LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
574
575 /* if here, we have either a new query or a retry on a previous query to process */
576 p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
577 SIZEOF_DNS_QUERY, PBUF_RAM);
578 if (p != NULL) {
579 LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
580 /* fill dns header */
581 hdr = (struct dns_hdr*)p->payload;
582 memset(hdr, 0, SIZEOF_DNS_HDR);
583 hdr->id = htons(id);
584 hdr->flags1 = DNS_FLAG1_RD;
585 hdr->numquestions = PP_HTONS(1);
586 query = (char*)hdr + SIZEOF_DNS_HDR;
587 pHostname = name;
588 --pHostname;
589
590 /* convert hostname into suitable query format. */
591 do {
592 ++pHostname;
593 nptr = query;
594 ++query;
595 for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
596 *query = *pHostname;
597 ++query;
598 ++n;
599 }
600 *nptr = n;
601 } while(*pHostname != 0);
602 *query++='\0';
603
604 /* fill dns query */
605 qry.type = PP_HTONS(DNS_RRTYPE_A);
606 qry.cls = PP_HTONS(DNS_RRCLASS_IN);
607 SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
608
609 /* resize pbuf to the exact dns query */
610 pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
611
612 /* connect to the server for faster receiving */
613 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
614 /* send dns packet */
615 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
616
617 /* free pbuf */
618 pbuf_free(p);
619 } else {
620 err = ERR_MEM;
621 }
622
623 return err;
624}
625
635static void
636dns_check_entry(u8_t i)
637{
638 err_t err;
639 struct dns_table_entry *pEntry = &dns_table[i];
640
641 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
642
643 switch(pEntry->state) {
644
645 case DNS_STATE_NEW: {
646 /* initialize new entry */
647 pEntry->state = DNS_STATE_ASKING;
648 pEntry->numdns = 0;
649 pEntry->tmr = 1;
650 pEntry->retries = 0;
651
652 /* send DNS packet for this entry */
653 err = dns_send(pEntry->numdns, pEntry->name, i);
654 if (err != ERR_OK) {
656 ("dns_send returned error: %s\n", lwip_strerr(err)));
657 }
658 break;
659 }
660
661 case DNS_STATE_ASKING: {
662 if (--pEntry->tmr == 0) {
663 if (++pEntry->retries == DNS_MAX_RETRIES) {
664 if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
665 /* change of server */
666 pEntry->numdns++;
667 pEntry->tmr = 1;
668 pEntry->retries = 0;
669 break;
670 } else {
671 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
672 /* call specified callback function if provided */
673 if (pEntry->found)
674 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
675 /* flush this entry */
676 pEntry->state = DNS_STATE_UNUSED;
677 pEntry->found = NULL;
678 break;
679 }
680 }
681
682 /* wait longer for the next retry */
683 pEntry->tmr = pEntry->retries;
684
685 /* send DNS packet for this entry */
686 err = dns_send(pEntry->numdns, pEntry->name, i);
687 if (err != ERR_OK) {
689 ("dns_send returned error: %s\n", lwip_strerr(err)));
690 }
691 }
692 break;
693 }
694
695 case DNS_STATE_DONE: {
696 /* if the time to live is nul */
697 if (--pEntry->ttl == 0) {
698 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
699 /* flush this entry */
700 pEntry->state = DNS_STATE_UNUSED;
701 pEntry->found = NULL;
702 }
703 break;
704 }
705 case DNS_STATE_UNUSED:
706 /* nothing to do */
707 break;
708 default:
709 LWIP_ASSERT("unknown dns_table entry state:", 0);
710 break;
711 }
712}
713
717static void
718dns_check_entries(void)
719{
720 u8_t i;
721
722 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
723 dns_check_entry(i);
724 }
725}
726
732static void
733dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
734{
735 u16_t i;
736 char *pHostname;
737 struct dns_hdr *hdr;
738 struct dns_answer ans;
739 struct dns_table_entry *pEntry;
740 u16_t nquestions, nanswers;
741
743 LWIP_UNUSED_ARG(pcb);
746
747 /* is the dns message too big ? */
748 if (p->tot_len > DNS_MSG_SIZE) {
749 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
750 /* free pbuf and return */
751 goto memerr;
752 }
753
754 /* is the dns message big enough ? */
755 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
756 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
757 /* free pbuf and return */
758 goto memerr;
759 }
760
761 /* copy dns payload inside static buffer for processing */
762 if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
763 /* The ID in the DNS header should be our entry into the name table. */
764 hdr = (struct dns_hdr*)dns_payload;
765 i = htons(hdr->id);
766 if (i < DNS_TABLE_SIZE) {
767 pEntry = &dns_table[i];
768 if(pEntry->state == DNS_STATE_ASKING) {
769 /* This entry is now completed. */
770 pEntry->state = DNS_STATE_DONE;
771 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
772
773 /* We only care about the question(s) and the answers. The authrr
774 and the extrarr are simply discarded. */
775 nquestions = htons(hdr->numquestions);
776 nanswers = htons(hdr->numanswers);
777
778 /* Check for error. If so, call callback to inform. */
779 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
780 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
781 /* call callback to indicate error, clean up memory and return */
782 goto responseerr;
783 }
784
785#if DNS_DOES_NAME_CHECK
786 /* Check if the name in the "question" part match with the name in the entry. */
787 if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
788 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
789 /* call callback to indicate error, clean up memory and return */
790 goto responseerr;
791 }
792#endif /* DNS_DOES_NAME_CHECK */
793
794 /* Skip the name in the "question" part */
795 pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
796
797 while (nanswers > 0) {
798 /* skip answer resource record's host name */
799 pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
800
801 /* Check for IP address type and Internet class. Others are discarded. */
802 SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
803 if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
804 (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
805 /* read the answer resource record's TTL, and maximize it if needed */
806 pEntry->ttl = ntohl(ans.ttl);
807 if (pEntry->ttl > DNS_MAX_TTL) {
808 pEntry->ttl = DNS_MAX_TTL;
809 }
810 /* read the IP address after answer resource record's header */
811 SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
812 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
813 ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
814 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
815 /* call specified callback function if provided */
816 if (pEntry->found) {
817 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
818 }
819 /* deallocate memory and return */
820 goto memerr;
821 } else {
822 pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
823 }
824 --nanswers;
825 }
826 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
827 /* call callback to indicate error, clean up memory and return */
828 goto responseerr;
829 }
830 }
831 }
832
833 /* deallocate memory and return */
834 goto memerr;
835
836responseerr:
837 /* ERROR: call specified callback function with NULL as name to indicate an error */
838 if (pEntry->found) {
839 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
840 }
841 /* flush this entry */
842 pEntry->state = DNS_STATE_UNUSED;
843 pEntry->found = NULL;
844
845memerr:
846 /* free pbuf */
847 pbuf_free(p);
848 return;
849}
850
859static err_t
860dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
861{
862 u8_t i;
863 u8_t lseq, lseqi;
864 struct dns_table_entry *pEntry = NULL;
865 size_t namelen;
866
867 /* search an unused entry, or the oldest one */
868 lseq = lseqi = 0;
869 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
870 pEntry = &dns_table[i];
871 /* is it an unused entry ? */
872 if (pEntry->state == DNS_STATE_UNUSED)
873 break;
874
875 /* check if this is the oldest completed entry */
876 if (pEntry->state == DNS_STATE_DONE) {
877 if ((dns_seqno - pEntry->seqno) > lseq) {
878 lseq = dns_seqno - pEntry->seqno;
879 lseqi = i;
880 }
881 }
882 }
883
884 /* if we don't have found an unused entry, use the oldest completed one */
885 if (i == DNS_TABLE_SIZE) {
886 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
887 /* no entry can't be used now, table is full */
888 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
889 return ERR_MEM;
890 } else {
891 /* use the oldest completed one */
892 i = lseqi;
893 pEntry = &dns_table[i];
894 }
895 }
896
897 /* use this entry */
898 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
899
900 /* fill the entry */
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;
908
909 /* force to send query without waiting timer */
910 dns_check_entry(i);
911
912 /* dns query is enqueued */
913 return ERR_INPROGRESS;
914}
915
935err_t
936dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
937 void *callback_arg)
938{
939 u32_t ipaddr;
940 /* not initialized or no valid server yet, or invalid addr pointer
941 * or invalid hostname or invalid hostname length */
942 if ((dns_pcb == NULL) || (addr == NULL) ||
943 (!hostname) || (!hostname[0]) ||
945 return ERR_ARG;
946 }
947
948#if LWIP_HAVE_LOOPIF
949 if (strcmp(hostname, "localhost")==0) {
951 return ERR_OK;
952 }
953#endif /* LWIP_HAVE_LOOPIF */
954
955 /* host name already in octet notation? set ip addr and return ERR_OK */
956 ipaddr = ipaddr_addr(hostname);
957 if (ipaddr == IPADDR_NONE) {
958 /* already have this address cached? */
959 ipaddr = dns_lookup(hostname);
960 }
961 if (ipaddr != IPADDR_NONE) {
962 ip4_addr_set_u32(addr, ipaddr);
963 return ERR_OK;
964 }
965
966 /* queue query with specified callback */
967 return dns_enqueue(hostname, found, callback_arg);
968}
969
970#endif /* LWIP_DNS */
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static int state
Definition: maze.c:121
#define PACK_STRUCT_END
Definition: arch.h:64
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define PACK_STRUCT_BEGIN
Definition: arch.h:60
#define PACK_STRUCT_FIELD(x)
Definition: arch.h:68
char * hostname
Definition: ftp.c:88
#define PP_HTONS(x)
Definition: def.h:88
#define LWIP_MIN(x, y)
Definition: def.h:44
#define NULL
Definition: types.h:112
USHORT port
Definition: uri.c:228
#define PACK_STRUCT_STRUCT
Definition: cc.h:59
#define U16_F
Definition: cc.h:36
unsigned long u32_t
Definition: cc.h:25
unsigned char u8_t
Definition: cc.h:23
unsigned short u16_t
Definition: cc.h:24
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:95
#define LWIP_DBG_LEVEL_WARNING
Definition: debug.h:46
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:66
#define ERR_MEM
Definition: err.h:53
#define ERR_ARG
Definition: err.h:70
#define ERR_OK
Definition: err.h:52
#define lwip_strerr(x)
Definition: err.h:78
#define ERR_INPROGRESS
Definition: err.h:57
s8_t err_t
Definition: err.h:47
#define LWIP_MEM_ALIGN_BUFFER(size)
Definition: mem.h:109
#define LWIP_MEM_ALIGN(addr)
Definition: mem.h:116
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLdouble n
Definition: glext.h:7729
GLint namelen
Definition: glext.h:7232
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
u32_t ipaddr_addr(const char *cp)
Definition: ip_addr.c:130
char hdr[14]
Definition: iptest.cpp:33
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
#define IP_ADDR_ANY
Definition: ip_addr.h:92
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
#define ip_addr_set_loopback(ipaddr)
Definition: ip_addr.h:172
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define IPADDR_NONE
Definition: ip_addr.h:96
#define ip4_addr_get_u32(src_ipaddr)
Definition: ip_addr.h:181
#define ip4_addr_set_u32(dest_ipaddr, src_u32)
Definition: ip_addr.h:179
#define ip_addr_debug_print(debug, ipaddr)
Definition: ip_addr.h:212
uint32_t entry
Definition: isohybrid.c:63
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
void * memp_malloc(memp_t type)
Definition: memp.c:390
void memp_free(memp_t type, void *mem)
Definition: memp.c:435
#define htons(x)
Definition: module.h:215
#define ntohl(x)
Definition: module.h:205
#define DNS_TABLE_SIZE
Definition: opt.h:823
#define DNS_MAX_NAME_LENGTH
Definition: opt.h:828
#define SMEMCPY(dst, src, len)
Definition: opt.h:92
#define DNS_MAX_SERVERS
Definition: opt.h:833
#define DNS_DEBUG
Definition: opt.h:2130
#define DNS_MSG_SIZE
Definition: opt.h:843
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:430
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:918
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
@ PBUF_RAM
Definition: pbuf.h:58
@ PBUF_TRANSPORT
Definition: pbuf.h:51
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
struct define * next
Definition: compiler.c:65
Definition: name.c:39
Definition: pbuf.h:79
void * arg
Definition: msvc.h:10