00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #include "lwip/opt.h"
00076
00077 #if LWIP_DNS
00078
00079 #include "lwip/udp.h"
00080 #include "lwip/mem.h"
00081 #include "lwip/dns.h"
00082
00083 #include <string.h>
00084
00085
00086 #ifndef DNS_SERVER_ADDRESS
00087 #define DNS_SERVER_ADDRESS inet_addr("208.67.222.222")
00088 #endif
00089
00090
00091 #ifndef DNS_SERVER_PORT
00092 #define DNS_SERVER_PORT 53
00093 #endif
00094
00095
00096 #ifndef DNS_MAX_RETRIES
00097 #define DNS_MAX_RETRIES 4
00098 #endif
00099
00100
00101 #ifndef DNS_MAX_TTL
00102 #define DNS_MAX_TTL 604800
00103 #endif
00104
00105
00106 #define DNS_FLAG1_RESPONSE 0x80
00107 #define DNS_FLAG1_OPCODE_STATUS 0x10
00108 #define DNS_FLAG1_OPCODE_INVERSE 0x08
00109 #define DNS_FLAG1_OPCODE_STANDARD 0x00
00110 #define DNS_FLAG1_AUTHORATIVE 0x04
00111 #define DNS_FLAG1_TRUNC 0x02
00112 #define DNS_FLAG1_RD 0x01
00113 #define DNS_FLAG2_RA 0x80
00114 #define DNS_FLAG2_ERR_MASK 0x0f
00115 #define DNS_FLAG2_ERR_NONE 0x00
00116 #define DNS_FLAG2_ERR_NAME 0x03
00117
00118
00119 #define DNS_STATE_UNUSED 0
00120 #define DNS_STATE_NEW 1
00121 #define DNS_STATE_ASKING 2
00122 #define DNS_STATE_DONE 3
00123
00124 #ifdef PACK_STRUCT_USE_INCLUDES
00125 # include "arch/bpstruct.h"
00126 #endif
00127 PACK_STRUCT_BEGIN
00128
00129 struct dns_hdr {
00130 PACK_STRUCT_FIELD(u16_t id);
00131 PACK_STRUCT_FIELD(u8_t flags1);
00132 PACK_STRUCT_FIELD(u8_t flags2);
00133 PACK_STRUCT_FIELD(u16_t numquestions);
00134 PACK_STRUCT_FIELD(u16_t numanswers);
00135 PACK_STRUCT_FIELD(u16_t numauthrr);
00136 PACK_STRUCT_FIELD(u16_t numextrarr);
00137 } PACK_STRUCT_STRUCT;
00138 PACK_STRUCT_END
00139 #ifdef PACK_STRUCT_USE_INCLUDES
00140 # include "arch/epstruct.h"
00141 #endif
00142 #define SIZEOF_DNS_HDR 12
00143
00144 #ifdef PACK_STRUCT_USE_INCLUDES
00145 # include "arch/bpstruct.h"
00146 #endif
00147 PACK_STRUCT_BEGIN
00148
00149 struct dns_query {
00150
00151
00152 PACK_STRUCT_FIELD(u16_t type);
00153 PACK_STRUCT_FIELD(u16_t class);
00154 } PACK_STRUCT_STRUCT;
00155 PACK_STRUCT_END
00156 #ifdef PACK_STRUCT_USE_INCLUDES
00157 # include "arch/epstruct.h"
00158 #endif
00159 #define SIZEOF_DNS_QUERY 4
00160
00161 #ifdef PACK_STRUCT_USE_INCLUDES
00162 # include "arch/bpstruct.h"
00163 #endif
00164 PACK_STRUCT_BEGIN
00165
00166 struct dns_answer {
00167
00168
00169 PACK_STRUCT_FIELD(u16_t type);
00170 PACK_STRUCT_FIELD(u16_t class);
00171 PACK_STRUCT_FIELD(u32_t ttl);
00172 PACK_STRUCT_FIELD(u16_t len);
00173 } PACK_STRUCT_STRUCT;
00174 PACK_STRUCT_END
00175 #ifdef PACK_STRUCT_USE_INCLUDES
00176 # include "arch/epstruct.h"
00177 #endif
00178 #define SIZEOF_DNS_ANSWER 10
00179
00180
00181 struct dns_table_entry {
00182 u8_t state;
00183 u8_t numdns;
00184 u8_t tmr;
00185 u8_t retries;
00186 u8_t seqno;
00187 u8_t err;
00188 u32_t ttl;
00189 char name[DNS_MAX_NAME_LENGTH];
00190 struct ip_addr ipaddr;
00191
00192 dns_found_callback found;
00193 void *arg;
00194 };
00195
00196 #if DNS_LOCAL_HOSTLIST
00197
00198 struct local_hostlist_entry {
00199
00200 const char *name;
00201
00202 u32_t addr;
00203 struct local_hostlist_entry *next;
00204 };
00205
00206 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
00207
00208
00209 static struct local_hostlist_entry *local_hostlist_dynamic;
00210 #else
00211
00212
00213
00214 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
00215 #define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
00216 #endif
00217
00218
00219 #ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
00220 #define DNS_LOCAL_HOSTLIST_STORAGE_POST
00221 #endif
00222 DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
00223 DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
00224
00225 #endif
00226
00227 static void dns_init_local();
00228 #endif
00229
00230
00231
00232 static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
00233 static void dns_check_entries(void);
00234
00235
00236
00237
00238
00239
00240 static struct udp_pcb *dns_pcb;
00241 static u8_t dns_seqno;
00242 static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
00243 static struct ip_addr dns_servers[DNS_MAX_SERVERS];
00244
00245 #if (DNS_USES_STATIC_BUF == 1)
00246 static u8_t dns_payload[DNS_MSG_SIZE];
00247 #endif
00248
00249
00250
00251
00252
00253 void
00254 dns_init()
00255 {
00256 struct ip_addr dnsserver;
00257
00258
00259 dnsserver.addr = DNS_SERVER_ADDRESS;
00260
00261 LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
00262
00263
00264 if (dns_pcb == NULL) {
00265 dns_pcb = udp_new();
00266
00267 if (dns_pcb != NULL) {
00268
00269
00270 LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
00271 DNS_STATE_UNUSED == 0);
00272
00273
00274 udp_bind(dns_pcb, IP_ADDR_ANY, 0);
00275 udp_recv(dns_pcb, dns_recv, NULL);
00276
00277
00278 dns_setserver(0, &dnsserver);
00279 }
00280 }
00281 #if DNS_LOCAL_HOSTLIST
00282 dns_init_local();
00283 #endif
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 void
00293 dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
00294 {
00295 if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
00296 (dnsserver != NULL) && (dnsserver->addr !=0 )) {
00297 dns_servers[numdns] = (*dnsserver);
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308 struct ip_addr
00309 dns_getserver(u8_t numdns)
00310 {
00311 if (numdns < DNS_MAX_SERVERS) {
00312 return dns_servers[numdns];
00313 } else {
00314 return *IP_ADDR_ANY;
00315 }
00316 }
00317
00318
00319
00320
00321
00322 void
00323 dns_tmr(void)
00324 {
00325 if (dns_pcb != NULL) {
00326 LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
00327 dns_check_entries();
00328 }
00329 }
00330
00331 #if DNS_LOCAL_HOSTLIST
00332 static void
00333 dns_init_local()
00334 {
00335 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
00336 int i;
00337 struct local_hostlist_entry *entry;
00338
00339 struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
00340 for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
00341 entry = mem_malloc(sizeof(struct local_hostlist_entry));
00342 LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
00343 if (entry != NULL) {
00344 struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
00345 entry->name = init_entry->name;
00346 entry->addr = init_entry->addr;
00347 entry->next = local_hostlist_dynamic;
00348 local_hostlist_dynamic = entry;
00349 }
00350 }
00351 #endif
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361 static u32_t
00362 dns_lookup_local(const char *hostname)
00363 {
00364 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
00365 struct local_hostlist_entry *entry = local_hostlist_dynamic;
00366 while(entry != NULL) {
00367 if(strcmp(entry->name, hostname) == 0) {
00368 return entry->addr;
00369 }
00370 entry = entry->next;
00371 }
00372 #else
00373 int i;
00374 for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
00375 if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
00376 return local_hostlist_static[i].addr;
00377 }
00378 }
00379 #endif
00380 return INADDR_NONE;
00381 }
00382
00383 #if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
00384
00385
00386
00387
00388
00389
00390
00391
00392 int
00393 dns_local_removehost(const char *hostname, const struct ip_addr *addr)
00394 {
00395 int removed = 0;
00396 struct local_hostlist_entry *entry = local_hostlist_dynamic;
00397 struct local_hostlist_entry *last_entry = NULL;
00398 while (entry != NULL) {
00399 if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
00400 ((addr == NULL) || (entry->addr == addr->addr))) {
00401 struct local_hostlist_entry *free_entry;
00402 if (last_entry != NULL) {
00403 last_entry->next = entry->next;
00404 } else {
00405 local_hostlist_dynamic = entry->next;
00406 }
00407 free_entry = entry;
00408 entry = entry->next;
00409 mem_free(free_entry);
00410 removed++;
00411 } else {
00412 last_entry = entry;
00413 entry = entry->next;
00414 }
00415 }
00416 return removed;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 err_t
00428 dns_local_addhost(const char *hostname, const struct ip_addr *addr)
00429 {
00430 struct local_hostlist_entry *entry;
00431 entry = mem_malloc(sizeof(struct local_hostlist_entry));
00432 if (entry == NULL) {
00433 return ERR_MEM;
00434 }
00435 entry->name = hostname;
00436 entry->addr = addr->addr;
00437 entry->next = local_hostlist_dynamic;
00438 local_hostlist_dynamic = entry;
00439 return ERR_OK;
00440 }
00441 #endif
00442 #endif
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 static u32_t
00458 dns_lookup(const char *name)
00459 {
00460 u8_t i;
00461 #if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
00462 u32_t addr;
00463 #endif
00464 #if DNS_LOCAL_HOSTLIST
00465 if ((addr = dns_lookup_local(name)) != INADDR_NONE) {
00466 return addr;
00467 }
00468 #endif
00469 #ifdef DNS_LOOKUP_LOCAL_EXTERN
00470 if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) {
00471 return addr;
00472 }
00473 #endif
00474
00475
00476 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
00477 if ((dns_table[i].state == DNS_STATE_DONE) &&
00478 (strcmp(name, dns_table[i].name) == 0)) {
00479 LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
00480 ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
00481 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
00482 return dns_table[i].ipaddr.addr;
00483 }
00484 }
00485
00486 return INADDR_NONE;
00487 }
00488
00489 #if DNS_DOES_NAME_CHECK
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 static u8_t
00501 dns_compare_name(unsigned char *query, unsigned char *response)
00502 {
00503 unsigned char n;
00504
00505 do {
00506 n = *response++;
00507
00508 if ((n & 0xc0) == 0xc0) {
00509
00510 break;
00511 } else {
00512
00513 while (n > 0) {
00514 if ((*query) != (*response)) {
00515 return 1;
00516 }
00517 ++response;
00518 ++query;
00519 --n;
00520 };
00521 ++query;
00522 }
00523 } while (*response != 0);
00524
00525 return 0;
00526 }
00527 #endif
00528
00529
00530
00531
00532
00533
00534
00535 static unsigned char *
00536 dns_parse_name(unsigned char *query)
00537 {
00538 unsigned char n;
00539
00540 do {
00541 n = *query++;
00542
00543 if ((n & 0xc0) == 0xc0) {
00544
00545 break;
00546 } else {
00547
00548 while (n > 0) {
00549 ++query;
00550 --n;
00551 };
00552 }
00553 } while (*query != 0);
00554
00555 return query + 1;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 static err_t
00568 dns_send(u8_t numdns, const char* name, u8_t id)
00569 {
00570 err_t err;
00571 struct dns_hdr *hdr;
00572 struct dns_query qry;
00573 struct pbuf *p;
00574 char *query, *nptr;
00575 const char *pHostname;
00576 u8_t n;
00577
00578 LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
00579 (u16_t)(numdns), name));
00580 LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
00581 LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0);
00582
00583
00584 p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
00585 SIZEOF_DNS_QUERY, PBUF_RAM);
00586 if (p != NULL) {
00587 LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
00588
00589 hdr = (struct dns_hdr*)p->payload;
00590 memset(hdr, 0, SIZEOF_DNS_HDR);
00591 hdr->id = htons(id);
00592 hdr->flags1 = DNS_FLAG1_RD;
00593 hdr->numquestions = htons(1);
00594 query = (char*)hdr + SIZEOF_DNS_HDR;
00595 pHostname = name;
00596 --pHostname;
00597
00598
00599 do {
00600 ++pHostname;
00601 nptr = query;
00602 ++query;
00603 for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
00604 *query = *pHostname;
00605 ++query;
00606 ++n;
00607 }
00608 *nptr = n;
00609 } while(*pHostname != 0);
00610 *query++='\0';
00611
00612
00613 qry.type = htons(DNS_RRTYPE_A);
00614 qry.class = htons(DNS_RRCLASS_IN);
00615 MEMCPY( query, &qry, SIZEOF_DNS_QUERY);
00616
00617
00618 pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)));
00619
00620
00621 udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
00622
00623 err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
00624
00625
00626 pbuf_free(p);
00627 } else {
00628 err = ERR_MEM;
00629 }
00630
00631 return err;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static void
00644 dns_check_entry(u8_t i)
00645 {
00646 struct dns_table_entry *pEntry = &dns_table[i];
00647
00648 LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
00649
00650 switch(pEntry->state) {
00651
00652 case DNS_STATE_NEW: {
00653
00654 pEntry->state = DNS_STATE_ASKING;
00655 pEntry->numdns = 0;
00656 pEntry->tmr = 1;
00657 pEntry->retries = 0;
00658
00659
00660 dns_send(pEntry->numdns, pEntry->name, i);
00661 break;
00662 }
00663
00664 case DNS_STATE_ASKING: {
00665 if (--pEntry->tmr == 0) {
00666 if (++pEntry->retries == DNS_MAX_RETRIES) {
00667 if ((pEntry->numdns+1<DNS_MAX_SERVERS) && (dns_servers[pEntry->numdns+1].addr!=0)) {
00668
00669 pEntry->numdns++;
00670 pEntry->tmr = 1;
00671 pEntry->retries = 0;
00672 break;
00673 } else {
00674 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
00675
00676 if (pEntry->found)
00677 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
00678
00679 pEntry->state = DNS_STATE_UNUSED;
00680 pEntry->found = NULL;
00681 break;
00682 }
00683 }
00684
00685
00686 pEntry->tmr = pEntry->retries;
00687
00688
00689 dns_send(pEntry->numdns, pEntry->name, i);
00690 }
00691 break;
00692 }
00693
00694 case DNS_STATE_DONE: {
00695
00696 if (--pEntry->ttl == 0) {
00697 LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
00698
00699 pEntry->state = DNS_STATE_UNUSED;
00700 pEntry->found = NULL;
00701 }
00702 break;
00703 }
00704 case DNS_STATE_UNUSED:
00705
00706 break;
00707 default:
00708 LWIP_ASSERT("unknown dns_table entry state:", 0);
00709 break;
00710 }
00711 }
00712
00713
00714
00715
00716 static void
00717 dns_check_entries(void)
00718 {
00719 u8_t i;
00720
00721 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
00722 dns_check_entry(i);
00723 }
00724 }
00725
00726
00727
00728
00729
00730
00731 static void
00732 dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
00733 {
00734 u8_t i;
00735 char *pHostname;
00736 struct dns_hdr *hdr;
00737 struct dns_answer ans;
00738 struct dns_table_entry *pEntry;
00739 u8_t nquestions, nanswers;
00740 #if (DNS_USES_STATIC_BUF == 0)
00741 u8_t dns_payload[DNS_MSG_SIZE];
00742 #endif
00743 #if (DNS_USES_STATIC_BUF == 2)
00744 u8_t* dns_payload;
00745 #endif
00746
00747 LWIP_UNUSED_ARG(arg);
00748 LWIP_UNUSED_ARG(pcb);
00749 LWIP_UNUSED_ARG(addr);
00750 LWIP_UNUSED_ARG(port);
00751
00752
00753 if (p->tot_len > DNS_MSG_SIZE) {
00754 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
00755
00756 goto memerr1;
00757 }
00758
00759
00760 if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
00761 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
00762
00763 goto memerr1;
00764 }
00765
00766 #if (DNS_USES_STATIC_BUF == 2)
00767 dns_payload = mem_malloc(p->tot_len);
00768 if (dns_payload == NULL) {
00769 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: mem_malloc error\n"));
00770
00771 goto memerr1;
00772 }
00773 #endif
00774
00775
00776 if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
00777
00778 hdr = (struct dns_hdr*)dns_payload;
00779 i = htons(hdr->id);
00780 if (i < DNS_TABLE_SIZE) {
00781 pEntry = &dns_table[i];
00782 if(pEntry->state == DNS_STATE_ASKING) {
00783
00784 pEntry->state = DNS_STATE_DONE;
00785 pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
00786
00787
00788
00789 nquestions = htons(hdr->numquestions);
00790 nanswers = htons(hdr->numanswers);
00791
00792
00793 if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
00794 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
00795
00796 goto responseerr;
00797 }
00798
00799 #if DNS_DOES_NAME_CHECK
00800
00801 if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
00802 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
00803
00804 goto responseerr;
00805 }
00806 #endif
00807
00808
00809 pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
00810
00811 while(nanswers > 0) {
00812
00813 pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
00814
00815
00816 MEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
00817 if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) {
00818
00819 pEntry->ttl = ntohl(ans.ttl);
00820 if (pEntry->ttl > DNS_MAX_TTL) {
00821 pEntry->ttl = DNS_MAX_TTL;
00822 }
00823
00824 MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr));
00825 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
00826 ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
00827 LWIP_DEBUGF(DNS_DEBUG, ("\n"));
00828
00829 if (pEntry->found) {
00830 (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
00831 }
00832
00833 goto memerr2;
00834 } else {
00835 pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
00836 }
00837 --nanswers;
00838 }
00839 LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
00840
00841 goto responseerr;
00842 }
00843 }
00844 }
00845
00846
00847 goto memerr2;
00848
00849 responseerr:
00850
00851 if (pEntry->found) {
00852 (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
00853 }
00854
00855 pEntry->state = DNS_STATE_UNUSED;
00856 pEntry->found = NULL;
00857
00858 memerr2:
00859 #if (DNS_USES_STATIC_BUF == 2)
00860
00861 mem_free(dns_payload);
00862 #endif
00863
00864 memerr1:
00865
00866 pbuf_free(p);
00867 return;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 static err_t
00879 dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
00880 {
00881 u8_t i;
00882 u8_t lseq, lseqi;
00883 struct dns_table_entry *pEntry = NULL;
00884
00885
00886 lseq = lseqi = 0;
00887 for (i = 0; i < DNS_TABLE_SIZE; ++i) {
00888 pEntry = &dns_table[i];
00889
00890 if (pEntry->state == DNS_STATE_UNUSED)
00891 break;
00892
00893
00894 if (pEntry->state == DNS_STATE_DONE) {
00895 if ((dns_seqno - pEntry->seqno) > lseq) {
00896 lseq = dns_seqno - pEntry->seqno;
00897 lseqi = i;
00898 }
00899 }
00900 }
00901
00902
00903 if (i == DNS_TABLE_SIZE) {
00904 if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
00905
00906 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
00907 return ERR_MEM;
00908 } else {
00909
00910 i = lseqi;
00911 pEntry = &dns_table[i];
00912 }
00913 }
00914
00915
00916 LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
00917
00918
00919 pEntry->state = DNS_STATE_NEW;
00920 pEntry->seqno = dns_seqno++;
00921 pEntry->found = found;
00922 pEntry->arg = callback_arg;
00923 strcpy(pEntry->name, name);
00924
00925
00926 dns_check_entry(i);
00927
00928
00929 return ERR_INPROGRESS;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 err_t
00951 dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback found,
00952 void *callback_arg)
00953 {
00954
00955
00956 if ((dns_pcb == NULL) || (addr == NULL) ||
00957 (!hostname) || (!hostname[0]) ||
00958 (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
00959 return ERR_VAL;
00960 }
00961
00962 #if LWIP_HAVE_LOOPIF
00963 if (strcmp(hostname,"localhost")==0) {
00964 addr->addr = htonl(INADDR_LOOPBACK);
00965 return ERR_OK;
00966 }
00967 #endif
00968
00969
00970
00971 if (((addr->addr = inet_addr(hostname)) != INADDR_NONE) ||
00972 ((addr->addr = dns_lookup(hostname)) != INADDR_NONE)) {
00973 return ERR_OK;
00974 }
00975
00976
00977 return dns_enqueue(hostname, found, callback_arg);
00978 }
00979
00980 #endif