Hi all! I'd like to share a small patch with you that allows the dns subsystem to remember and handle more then one IP address from response messages. It basically parses out all IP address and stores them in an array. It then returns a random entry. The patch was created against lwip 2.0.0RC2 and requires LWIP_RAND(). I hope it might be as useful for others as it was for us.
Jan
Index: lwip/lwip/src/core/dns.c =================================================================== --- lwip/lwip/src/core/dns.c (revision 6302) +++ lwip/lwip/src/core/dns.c (revision 6303) @@ -135,6 +135,11 @@ #define DNS_MAX_REQUESTS DNS_TABLE_SIZE #endif +/** DNS maximum number of addresses to remember */ +#ifndef DNS_MAX_ADDRESSES_PER_ENTRY +#define DNS_MAX_ADDRESSES_PER_ENTRY 4 +#endif + /* The number of UDP source ports used in parallel */ #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) #ifndef DNS_MAX_SOURCE_PORTS @@ -257,7 +262,7 @@ /** DNS table entry */ struct dns_table_entry { u32_t ttl; - ip_addr_t ipaddr; + ip_addr_t ipaddr[DNS_MAX_ADDRESSES_PER_ENTRY]; u16_t txid; u8_t state; u8_t server_idx; @@ -267,6 +272,7 @@ #if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) u8_t pcb_idx; #endif + u8_t num_addr; // number of addresses in ipaddr array char name[DNS_MAX_NAME_LENGTH]; #if LWIP_IPV4 && LWIP_IPV6 u8_t reqaddrtype; @@ -641,7 +647,8 @@ ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); LWIP_DEBUGF(DNS_DEBUG, ("\n")); if (addr) { - ip_addr_copy(*addr, dns_table[i].ipaddr); + // select a random address to return + ip_addr_copy(*addr, dns_table[i].ipaddr[LWIP_RAND() % dns_table[i].num_addr]); } return ERR_OK; } @@ -1080,7 +1087,8 @@ if (entry->ttl > DNS_MAX_TTL) { entry->ttl = DNS_MAX_TTL; } - dns_call_found(idx, &entry->ipaddr); + // call found callback with random ip + dns_call_found(idx, &entry->ipaddr[LWIP_RAND() % entry->num_addr]); if (entry->ttl == 0) { /* RFC 883, page 29: "Zero values are @@ -1108,6 +1116,8 @@ struct dns_answer ans; struct dns_query qry; u16_t nquestions, nanswers; + u8_t num_addr; + u32_t ttl; LWIP_UNUSED_ARG(arg); LWIP_UNUSED_ARG(pcb); @@ -1173,6 +1183,8 @@ if (hdr.flags2 & DNS_FLAG2_ERR_MASK) { LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); } else { + num_addr = 0; // initialize counter to number of addresses extracted + ttl = DNS_MAX_TTL; // initialize ttl to maximum values, we'll use minimum of all entries found while ((nanswers > 0) && (res_idx < p->tot_len)) { /* skip answer resource record's host name */ res_idx = dns_parse_name(p, res_idx); @@ -1187,14 +1199,15 @@ if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) #endif /* LWIP_IPV4 && LWIP_IPV6 */ { - ip4_addr_t ip4addr; - /* read the IP address after answer resource record's header */ - pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx); - ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, ntohl(ans.ttl)); - return; + if (num_addr < DNS_MAX_ADDRESSES_PER_ENTRY) + { + ip4_addr_t ip4addr; + /* read the IP address after answer resource record's header */ + pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx); + ip_addr_copy_from_ip4(dns_table[i].ipaddr[num_addr++], ip4addr); + if (ttl > ntohl(ans.ttl)) + ttl = ntohl(ans.ttl); + } } } #endif /* LWIP_IPV4 */ @@ -1204,14 +1217,15 @@ if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) #endif /* LWIP_IPV4 && LWIP_IPV6 */ { - ip6_addr_t ip6addr; - /* read the IP address after answer resource record's header */ - pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx); - ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, ntohl(ans.ttl)); - return; + if (num_addr < DNS_MAX_ADDRESSES_PER_ENTRY) + { + ip6_addr_t ip6addr; + /* read the IP address after answer resource record's header */ + pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx); + ip_addr_copy_from_ip6(dns_table[i].ipaddr[num_addr++], ip6addr); + if (ttl > ntohl(ans.ttl)) + ttl = ntohl(ans.ttl); + } } } #endif /* LWIP_IPV6 */ @@ -1220,6 +1234,17 @@ res_idx += htons(ans.len); --nanswers; } + // remember number of addresses extracted + dns_table[i].num_addr = num_addr; + // finish good entries + if (num_addr > 0) + { + pbuf_free(p); + /* handle correct response */ + dns_correct_response(i, ttl); + return; + } + #if LWIP_IPV4 && LWIP_IPV6 if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) {
_______________________________________________ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users