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

Reply via email to