Warning, cross-references for /kernel/lwip/core/dns.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 #include "lwip/opt.h"
0076
0077 #if LWIP_DNS
0078
0079 #include "lwip/udp.h"
0080 #include "lwip/mem.h"
0081 #include "lwip/dns.h"
0082
0083 #include <string.h>
0084
0085
0086 #ifndef DNS_SERVER_ADDRESS
0087 #define DNS_SERVER_ADDRESS inet_addr("208.67.222.222")
0088 #endif
0089
0090
0091 #ifndef DNS_SERVER_PORT
0092 #define DNS_SERVER_PORT 53
0093 #endif
0094
0095
0096 #ifndef DNS_MAX_RETRIES
0097 #define DNS_MAX_RETRIES 4
0098 #endif
0099
0100
0101 #ifndef DNS_MAX_TTL
0102 #define DNS_MAX_TTL 604800
0103 #endif
0104
0105
0106 #define DNS_FLAG1_RESPONSE 0x80
0107 #define DNS_FLAG1_OPCODE_STATUS 0x10
0108 #define DNS_FLAG1_OPCODE_INVERSE 0x08
0109 #define DNS_FLAG1_OPCODE_STANDARD 0x00
0110 #define DNS_FLAG1_AUTHORATIVE 0x04
0111 #define DNS_FLAG1_TRUNC 0x02
0112 #define DNS_FLAG1_RD 0x01
0113 #define DNS_FLAG2_RA 0x80
0114 #define DNS_FLAG2_ERR_MASK 0x0f
0115 #define DNS_FLAG2_ERR_NONE 0x00
0116 #define DNS_FLAG2_ERR_NAME 0x03
0117
0118
0119 #define DNS_STATE_UNUSED 0
0120 #define DNS_STATE_NEW 1
0121 #define DNS_STATE_ASKING 2
0122 #define DNS_STATE_DONE 3
0123
0124 #ifdef PACK_STRUCT_USE_INCLUDES
0125 # include "arch/bpstruct.h"
0126 #endif
0127 PACK_STRUCT_BEGIN
0128
0129 struct dns_hdr {
0130 PACK_STRUCT_FIELD(u16_t id);
0131 PACK_STRUCT_FIELD(u8_t flags1);
0132 PACK_STRUCT_FIELD(u8_t flags2);
0133 PACK_STRUCT_FIELD(u16_t numquestions);
0134 PACK_STRUCT_FIELD(u16_t numanswers);
0135 PACK_STRUCT_FIELD(u16_t numauthrr);
0136 PACK_STRUCT_FIELD(u16_t numextrarr);
0137 } PACK_STRUCT_STRUCT;
0138 PACK_STRUCT_END
0139 #ifdef PACK_STRUCT_USE_INCLUDES
0140 # include "arch/epstruct.h"
0141 #endif
0142 #define SIZEOF_DNS_HDR 12
0143
0144 #ifdef PACK_STRUCT_USE_INCLUDES
0145 # include "arch/bpstruct.h"
0146 #endif
0147 PACK_STRUCT_BEGIN
0148
0149 struct dns_query {
0150
0151
0152 PACK_STRUCT_FIELD(u16_t type);
0153 PACK_STRUCT_FIELD(u16_t class);
0154 } PACK_STRUCT_STRUCT;
0155 PACK_STRUCT_END
0156 #ifdef PACK_STRUCT_USE_INCLUDES
0157 # include "arch/epstruct.h"
0158 #endif
0159 #define SIZEOF_DNS_QUERY 4
0160
0161 #ifdef PACK_STRUCT_USE_INCLUDES
0162 # include "arch/bpstruct.h"
0163 #endif
0164 PACK_STRUCT_BEGIN
0165
0166 struct dns_answer {
0167
0168
0169 PACK_STRUCT_FIELD(u16_t type);
0170 PACK_STRUCT_FIELD(u16_t class);
0171 PACK_STRUCT_FIELD(u32_t ttl);
0172 PACK_STRUCT_FIELD(u16_t len);
0173 } PACK_STRUCT_STRUCT;
0174 PACK_STRUCT_END
0175 #ifdef PACK_STRUCT_USE_INCLUDES
0176 # include "arch/epstruct.h"
0177 #endif
0178 #define SIZEOF_DNS_ANSWER 10
0179
0180
0181 struct dns_table_entry {
0182 u8_t state;
0183 u8_t numdns;
0184 u8_t tmr;
0185 u8_t retries;
0186 u8_t seqno;
0187 u8_t err;
0188 u32_t ttl;
0189 char name[DNS_MAX_NAME_LENGTH];
0190 struct ip_addr ipaddr;
0191
0192 dns_found_callback found;
0193 void *arg;
0194 };
0195
0196 #if DNS_LOCAL_HOSTLIST
0197
0198 struct local_hostlist_entry {
0199
0200 const char *name;
0201
0202 u32_t addr;
0203 struct local_hostlist_entry *next;
0204 };
0205
0206 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
0207
0208
0209 static struct local_hostlist_entry *local_hostlist_dynamic;
0210 #else
0211
0212
0213
0214 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
0215 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
0216 #endif
0217
0218
0219 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
0220 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
0221 #endif
0222 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
0223 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
0224
0225 #endif
0226
0227 static void dns_init_local();
0228 #endif
0229
0230
0231
0232 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
0233 static void dns_check_entries(void);
0234
0235
0236
0237
0238
0239
0240 static struct udp_pcb *dns_pcb;
0241 static u8_t dns_seqno;
0242 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
0243 static struct ip_addr dns_servers[DNS_MAX_SERVERS];
0244
0245 #if (DNS_USES_STATIC_BUF == 1)
0246 static u8_t dns_payload[DNS_MSG_SIZE];
0247 #endif
0248
0249
0250
0251
0252
0253 void
0254 dns_init()
0255 {
0256 struct ip_addr dnsserver;
0257
0258
0259 dnsserver.addr = DNS_SERVER_ADDRESS;
0260
0261 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
0262
0263
0264 if (dns_pcb == NULL) {
0265 dns_pcb = udp_new();
0266
0267 if (dns_pcb != NULL) {
0268
0269
0270 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
0271 DNS_STATE_UNUSED == 0);
0272
0273
0274 udp_bind(dns_pcb, IP_ADDR_ANY, 0);
0275 udp_recv(dns_pcb, dns_recv, NULL);
0276
0277
0278 dns_setserver(0, &dnsserver);
0279 }
0280 }
0281 #if DNS_LOCAL_HOSTLIST
0282 dns_init_local();
0283 #endif
0284 }
0285
0286
0287
0288
0289
0290
0291
0292 void
0293 dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
0294 {
0295 if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
0296 (dnsserver != NULL) && (dnsserver->addr !=0 )) {
0297 dns_servers[numdns] = (*dnsserver);
0298 }
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308 struct ip_addr
0309 dns_getserver(u8_t numdns)
0310 {
0311 if (numdns < DNS_MAX_SERVERS) {
0312 return dns_servers[numdns];
0313 } else {
0314 return *IP_ADDR_ANY;
0315 }
0316 }
0317
0318
0319
0320
0321
0322 void
0323 dns_tmr(void)
0324 {
0325 if (dns_pcb != NULL) {
0326 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
0327 dns_check_entries();
0328 }
0329 }
0330
0331 #if DNS_LOCAL_HOSTLIST
0332 static void
0333 dns_init_local()
0334 {
0335 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
0336 int i;
0337 struct local_hostlist_entry *entry;
0338
0339 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
0340 for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
0341 entry = mem_malloc(sizeof(struct local_hostlist_entry));
0342 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
0343 if (entry != NULL) {
0344 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
0345 entry->name = init_entry->name;
0346 entry->addr = init_entry->addr;
0347 entry->next = local_hostlist_dynamic;
0348 local_hostlist_dynamic = entry;
0349 }
0350 }
0351 #endif
0352 }
0353
0354
0355
0356
0357
0358
0359
0360
0361 static u32_t
0362 dns_lookup_local(const char *hostname)
0363 {
0364 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
0365 struct local_hostlist_entry *entry = local_hostlist_dynamic;
0366 while(entry != NULL) {
0367 if(strcmp(entry->name, hostname) == 0) {
0368 return entry->addr;
0369 }
0370 entry = entry->next;
0371 }
0372 #else
0373 int i;
0374 for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
0375 if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
0376 return local_hostlist_static[i].addr;
0377 }
0378 }
0379 #endif
0380 return INADDR_NONE;
0381 }
0382
0383 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
0384
0385
0386
0387
0388
0389
0390
0391
0392 int
0393 dns_local_removehost(const char *hostname, const struct ip_addr *addr)
0394 {
0395 int removed = 0;
0396 struct local_hostlist_entry *entry = local_hostlist_dynamic;
0397 struct local_hostlist_entry *last_entry = NULL;
0398 while (entry != NULL) {
0399 if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
0400 ((addr == NULL) || (entry->addr == addr->addr))) {
0401 struct local_hostlist_entry *free_entry;
0402 if (last_entry != NULL) {
0403 last_entry->next = entry->next;
0404 } else {
0405 local_hostlist_dynamic = entry->next;
0406 }
0407 free_entry = entry;
0408 entry = entry->next;
0409 mem_free(free_entry);
0410 removed++;
0411 } else {
0412 last_entry = entry;
0413 entry = entry->next;
0414 }
0415 }
0416 return removed;
0417 }
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 err_t
0428 dns_local_addhost(const char *hostname, const struct ip_addr *addr)
0429 {
0430 struct local_hostlist_entry *entry;
0431 entry = mem_malloc(sizeof(struct local_hostlist_entry));
0432 if (entry == NULL) {
0433 return ERR_MEM;
0434 }
0435 entry->name = hostname;
0436 entry->addr = addr->addr;
0437 entry->next = local_hostlist_dynamic;
0438 local_hostlist_dynamic = entry;
0439 return ERR_OK;
0440 }
0441 #endif
0442 #endif
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 static u32_t
0458 dns_lookup(const char *name)
0459 {
0460 u8_t i;
0461 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
0462 u32_t addr;
0463 #endif
0464 #if DNS_LOCAL_HOSTLIST
0465 if ((addr = dns_lookup_local(name)) != INADDR_NONE) {
0466 return addr;
0467 }
0468 #endif
0469 #ifdef DNS_LOOKUP_LOCAL_EXTERN
0470 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) {
0471 return addr;
0472 }
0473 #endif
0474
0475
0476 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
0477 if ((dns_table[i].state == DNS_STATE_DONE) &&
0478 (strcmp(name, dns_table[i].name) == 0)) {
0479 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
0480 ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
0481 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
0482 return dns_table[i].ipaddr.addr;
0483 }
0484 }
0485
0486 return INADDR_NONE;
0487 }
0488
0489 #if DNS_DOES_NAME_CHECK
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 static u8_t
0501 dns_compare_name(unsigned char *query, unsigned char *response)
0502 {
0503 unsigned char n;
0504
0505 do {
0506 n = *response++;
0507
0508 if ((n & 0xc0) == 0xc0) {
0509
0510 break;
0511 } else {
0512
0513 while (n > 0) {
0514 if ((*query) != (*response)) {
0515 return 1;
0516 }
0517 ++response;
0518 ++query;
0519 --n;
0520 };
0521 ++query;
0522 }
0523 } while (*response != 0);
0524
0525 return 0;
0526 }
0527 #endif
0528
0529
0530
0531
0532
0533
0534
0535 static unsigned char *
0536 dns_parse_name(unsigned char *query)
0537 {
0538 unsigned char n;
0539
0540 do {
0541 n = *query++;
0542
0543 if ((n & 0xc0) == 0xc0) {
0544
0545 break;
0546 } else {
0547
0548 while (n > 0) {
0549 ++query;
0550 --n;
0551 };
0552 }
0553 } while (*query != 0);
0554
0555 return query + 1;
0556 }
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 static err_t
0568 dns_send(u8_t numdns, const char* name, u8_t id)
0569 {
0570 err_t err;
0571 struct dns_hdr *hdr;
0572 struct dns_query qry;
0573 struct pbuf *p;
0574 char *query, *nptr;
0575 const char *pHostname;
0576 u8_t n;
0577
0578 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
0579 (u16_t)(numdns), name));
0580 LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
0581 LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0);
0582
0583
0584 p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
0585 SIZEOF_DNS_QUERY, PBUF_RAM);
0586 if (p != NULL) {
0587 LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
0588
0589 hdr = (struct dns_hdr*)p->payload;
0590 memset(hdr, 0, SIZEOF_DNS_HDR);
0591 hdr->id = htons(id);
0592 hdr->flags1 = DNS_FLAG1_RD;
0593 hdr->numquestions = htons(1);
0594 query = (char*)hdr + SIZEOF_DNS_HDR;
0595 pHostname = name;
0596 --pHostname;
0597
0598
0599 do {
0600 ++pHostname;
0601 nptr = query;
0602 ++query;
0603 for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
0604 *query = *pHostname;
0605 ++query;
0606 ++n;
0607 }
0608 *nptr = n;
0609 } while(*pHostname != 0);
0610 *query++='\0';
0611
0612
0613 qry.type = htons(DNS_RRTYPE_A);
0614 qry.class = htons(DNS_RRCLASS_IN);
0615 MEMCPY( query, &qry, SIZEOF_DNS_QUERY);
0616
0617
0618 pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)));
0619
0620
0621 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
0622
0623 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
0624
0625
0626 pbuf_free(p);
0627 } else {
0628 err = ERR_MEM;
0629 }
0630
0631 return err;
0632 }
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643 static void
0644 dns_check_entry(u8_t i)
0645 {
0646 struct dns_table_entry *pEntry = &dns_table[i];
0647
0648 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
0649
0650 switch(pEntry->state) {
0651
0652 case DNS_STATE_NEW: {
0653
0654 pEntry->state = DNS_STATE_ASKING;
0655 pEntry->numdns = 0;
0656 pEntry->tmr = 1;
0657 pEntry->retries = 0;
0658
0659
0660 dns_send(pEntry->numdns, pEntry->name, i);
0661 break;
0662 }
0663
0664 case DNS_STATE_ASKING: {
0665 if (--pEntry->tmr == 0) {
0666 if (++pEntry->retries == DNS_MAX_RETRIES) {
0667 if ((pEntry->numdns+1<DNS_MAX_SERVERS) && (dns_servers[pEntry->numdns+1].addr!=0)) {
0668
0669 pEntry->numdns++;
0670 pEntry->tmr = 1;
0671 pEntry->retries = 0;
0672 break;
0673 } else {
0674 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
0675
0676 if (pEntry->found)
0677 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
0678
0679 pEntry->state = DNS_STATE_UNUSED;
0680 pEntry->found = NULL;
0681 break;
0682 }
0683 }
0684
0685
0686 pEntry->tmr = pEntry->retries;
0687
0688
0689 dns_send(pEntry->numdns, pEntry->name, i);
0690 }
0691 break;
0692 }
0693
0694 case DNS_STATE_DONE: {
0695
0696 if (--pEntry->ttl == 0) {
0697 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
0698
0699 pEntry->state = DNS_STATE_UNUSED;
0700 pEntry->found = NULL;
0701 }
0702 break;
0703 }
0704 case DNS_STATE_UNUSED:
0705
0706 break;
0707 default:
0708 LWIP_ASSERT("unknown dns_table entry state:", 0);
0709 break;
0710 }
0711 }
0712
0713
0714
0715
0716 static void
0717 dns_check_entries(void)
0718 {
0719 u8_t i;
0720
0721 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
0722 dns_check_entry(i);
0723 }
0724 }
0725
0726
0727
0728
0729
0730
0731 static void
0732 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
0733 {
0734 u8_t i;
0735 char *pHostname;
0736 struct dns_hdr *hdr;
0737 struct dns_answer ans;
0738 struct dns_table_entry *pEntry;
0739 u8_t nquestions, nanswers;
0740 #if (DNS_USES_STATIC_BUF == 0)
0741 u8_t dns_payload[DNS_MSG_SIZE];
0742 #endif
0743 #if (DNS_USES_STATIC_BUF == 2)
0744 u8_t* dns_payload;
0745 #endif
0746
0747 LWIP_UNUSED_ARG(arg);
0748 LWIP_UNUSED_ARG(pcb);
0749 LWIP_UNUSED_ARG(addr);
0750 LWIP_UNUSED_ARG(port);
0751
0752
0753 if (p->tot_len > DNS_MSG_SIZE) {
0754 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
0755
0756 goto memerr1;
0757 }
0758
0759
0760 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
0761 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
0762
0763 goto memerr1;
0764 }
0765
0766 #if (DNS_USES_STATIC_BUF == 2)
0767 dns_payload = mem_malloc(p->tot_len);
0768 if (dns_payload == NULL) {
0769 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: mem_malloc error\n"));
0770
0771 goto memerr1;
0772 }
0773 #endif
0774
0775
0776 if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
0777
0778 hdr = (struct dns_hdr*)dns_payload;
0779 i = htons(hdr->id);
0780 if (i < DNS_TABLE_SIZE) {
0781 pEntry = &dns_table[i];
0782 if(pEntry->state == DNS_STATE_ASKING) {
0783
0784 pEntry->state = DNS_STATE_DONE;
0785 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
0786
0787
0788
0789 nquestions = htons(hdr->numquestions);
0790 nanswers = htons(hdr->numanswers);
0791
0792
0793 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
0794 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
0795
0796 goto responseerr;
0797 }
0798
0799 #if DNS_DOES_NAME_CHECK
0800
0801 if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
0802 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
0803
0804 goto responseerr;
0805 }
0806 #endif
0807
0808
0809 pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
0810
0811 while(nanswers > 0) {
0812
0813 pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
0814
0815
0816 MEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
0817 if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) {
0818
0819 pEntry->ttl = ntohl(ans.ttl);
0820 if (pEntry->ttl > DNS_MAX_TTL) {
0821 pEntry->ttl = DNS_MAX_TTL;
0822 }
0823
0824 MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr));
0825 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
0826 ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
0827 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
0828
0829 if (pEntry->found) {
0830 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
0831 }
0832
0833 goto memerr2;
0834 } else {
0835 pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
0836 }
0837 --nanswers;
0838 }
0839 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
0840
0841 goto responseerr;
0842 }
0843 }
0844 }
0845
0846
0847 goto memerr2;
0848
0849 responseerr:
0850
0851 if (pEntry->found) {
0852 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
0853 }
0854
0855 pEntry->state = DNS_STATE_UNUSED;
0856 pEntry->found = NULL;
0857
0858 memerr2:
0859 #if (DNS_USES_STATIC_BUF == 2)
0860
0861 mem_free(dns_payload);
0862 #endif
0863
0864 memerr1:
0865
0866 pbuf_free(p);
0867 return;
0868 }
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878 static err_t
0879 dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
0880 {
0881 u8_t i;
0882 u8_t lseq, lseqi;
0883 struct dns_table_entry *pEntry = NULL;
0884
0885
0886 lseq = lseqi = 0;
0887 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
0888 pEntry = &dns_table[i];
0889
0890 if (pEntry->state == DNS_STATE_UNUSED)
0891 break;
0892
0893
0894 if (pEntry->state == DNS_STATE_DONE) {
0895 if ((dns_seqno - pEntry->seqno) > lseq) {
0896 lseq = dns_seqno - pEntry->seqno;
0897 lseqi = i;
0898 }
0899 }
0900 }
0901
0902
0903 if (i == DNS_TABLE_SIZE) {
0904 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
0905
0906 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
0907 return ERR_MEM;
0908 } else {
0909
0910 i = lseqi;
0911 pEntry = &dns_table[i];
0912 }
0913 }
0914
0915
0916 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
0917
0918
0919 pEntry->state = DNS_STATE_NEW;
0920 pEntry->seqno = dns_seqno++;
0921 pEntry->found = found;
0922 pEntry->arg = callback_arg;
0923 strcpy(pEntry->name, name);
0924
0925
0926 dns_check_entry(i);
0927
0928
0929 return ERR_INPROGRESS;
0930 }
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950 err_t
0951 dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback found,
0952 void *callback_arg)
0953 {
0954
0955
0956 if ((dns_pcb == NULL) || (addr == NULL) ||
0957 (!hostname) || (!hostname[0]) ||
0958 (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
0959 return ERR_VAL;
0960 }
0961
0962 #if LWIP_HAVE_LOOPIF
0963 if (strcmp(hostname,"localhost")==0) {
0964 addr->addr = htonl(INADDR_LOOPBACK);
0965 return ERR_OK;
0966 }
0967 #endif
0968
0969
0970
0971 if (((addr->addr = inet_addr(hostname)) != INADDR_NONE) ||
0972 ((addr->addr = dns_lookup(hostname)) != INADDR_NONE)) {
0973 return ERR_OK;
0974 }
0975
0976
0977 return dns_enqueue(hostname, found, callback_arg);
0978 }
0979
0980 #endif