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