From b02b94ba5e7ae28ac0b7c2fdd0da11588e501219 Mon Sep 17 00:00:00 2001
From: Ashley Duncan <ashley.duncan@evnex.com>
Date: Thu, 25 Jun 2020 10:50:49 +1200
Subject: [PATCH] Changes to lwIP to allow DNS servers per network interface.

---
 Components/lwIP/lwip-2.1.2/src/core/dns.c          | 56 +++++++++++++++-------
 Components/lwIP/lwip-2.1.2/src/core/ipv4/dhcp.c    |  2 +-
 Components/lwIP/lwip-2.1.2/src/core/netif.c        |  9 +++-
 Components/lwIP/lwip-2.1.2/src/include/lwip/dns.h  | 13 ++++-
 .../lwIP/lwip-2.1.2/src/include/lwip/netif.h       |  3 ++
 Components/lwIP/lwip-2.1.2/src/netif/ppp/ppp.c     | 20 +++++---
 6 files changed, 75 insertions(+), 28 deletions(-)

diff --git a/Components/lwIP/lwip-2.1.2/src/core/dns.c b/Components/lwIP/lwip-2.1.2/src/core/dns.c
index 737b3393..c870d3e2 100644
--- a/Components/lwIP/lwip-2.1.2/src/core/dns.c
+++ b/Components/lwIP/lwip-2.1.2/src/core/dns.c
@@ -356,17 +356,27 @@ dns_init(void)
  *
  * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
  * @param dnsserver IP address of the DNS server to set
+ * @param netif specific netif to set DNS server on.  If NULL, set default DNS server
+ *         (requires LWIP_DNS_SERVER_PER_NETIF)
  */
 void
-dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
+dns_setserver(u8_t numdns, const ip_addr_t *dnsserver LWIP_DNS_NETIF_ARG(struct netif *netif))
 {
-  if (numdns < DNS_MAX_SERVERS) {
-    if (dnsserver != NULL) {
-      dns_servers[numdns] = (*dnsserver);
-    } else {
-      dns_servers[numdns] = *IP_ADDR_ANY;
-    }
+  if (numdns >= DNS_MAX_SERVERS) {
+    return;
+  }
+#if LWIP_DNS_SERVER_PER_NETIF
+  if (netif) {
+    netif->dns_servers[numdns] = *dnsserver;
+  } else {
+    dns_servers[numdns] = *dnsserver;
   }
+  LWIP_DEBUGF(DNS_DEBUG, ("DNS server [%"U16_F"] for %.2s%"U16_F" set to %s\n", (u16_t)numdns, 
+              netif ? netif->name : "All", netif ? (u16_t)netif->num : 0, ipaddr_ntoa(dnsserver)));
+#else
+  dns_servers[numdns] = *dnsserver;
+  LWIP_DEBUGF(DNS_DEBUG, ("DNS server [%"U16_F"] set to %s\n", (u16_t)numdns, ipaddr_ntoa(dnsserver)));
+#endif /*LWIP_DNS_SERVER_PER_NETIF*/
 }
 
 /**
@@ -374,17 +384,27 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
  * Obtain one of the currently configured DNS server.
  *
  * @param numdns the index of the DNS server
+ * @param netif specific netif to fetch server from if not NULL, else fetch default DNS server 
+ *         (requires LWIP_DNS_SERVER_PER_NETIF)
  * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
- *         server has not been configured.
+ *         server has not been configured.  For the cases where a netif specific DNS server is
+ *         returned, the pointer is to the dns_servers entry in the netif structure, do not store
+ *         the returned pointer persistently in the case where the netif may be destroyed
  */
 const ip_addr_t *
-dns_getserver(u8_t numdns)
+dns_getserver(u8_t numdns LWIP_DNS_NETIF_ARG(struct netif *netif))
 {
-  if (numdns < DNS_MAX_SERVERS) {
-    return &dns_servers[numdns];
-  } else {
+  if (numdns >= DNS_MAX_SERVERS) {
     return IP_ADDR_ANY;
   }
+#if LWIP_DNS_SERVER_PER_NETIF
+  if (netif) {
+      if (!ip_addr_isany(&netif->dns_servers[numdns])) {
+        return &netif->dns_servers[numdns];
+      }
+  }
+#endif /*LWIP_DNS_SERVER_PER_NETIF*/
+  return &dns_servers[numdns];
 }
 
 /**
@@ -757,10 +777,10 @@ dns_send(u8_t idx)
   u8_t pcb_idx;
   struct dns_table_entry *entry = &dns_table[idx];
 
-  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
+  LWIP_DEBUGF(DNS_DEBUG, ("dns_send: server_idx %"U16_F" \"%s\": request\n",
                           (u16_t)(entry->server_idx), entry->name));
   LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
-  if (ip_addr_isany_val(dns_servers[entry->server_idx])
+  if (ip_addr_isany(dns_getserver(entry->server_idx LWIP_DNS_NETIF_ARG(netif_default)))
 #if LWIP_DNS_SUPPORT_MDNS_QUERIES
       && !entry->is_mdns
 #endif
@@ -845,7 +865,7 @@ dns_send(u8_t idx)
 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
     {
       dst_port = DNS_SERVER_PORT;
-      dst = &dns_servers[entry->server_idx];
+      dst = dns_getserver(entry->server_idx LWIP_DNS_NETIF_ARG(netif_default));
     }
     err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port);
 
@@ -1026,7 +1046,7 @@ dns_backupserver_available(struct dns_table_entry *pentry)
   u8_t ret = 0;
 
   if (pentry) {
-    if ((pentry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[pentry->server_idx + 1])) {
+    if ((pentry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany(dns_getserver(pentry->server_idx + 1 LWIP_DNS_NETIF_ARG(netif_default)))) {
       ret = 1;
     }
   }
@@ -1218,7 +1238,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr,
         {
           /* Check whether response comes from the same network address to which the
              question was sent. (RFC 5452) */
-          if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) {
+          if (!ip_addr_cmp(addr, dns_getserver(entry->server_idx LWIP_DNS_NETIF_ARG(netif_default)))) {
             goto ignore_packet; /* ignore this packet */
           }
         }
@@ -1618,7 +1638,7 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
 #endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */
   {
     /* prevent calling found callback if no server is set, return error instead */
-    if (ip_addr_isany_val(dns_servers[0])) {
+    if (ip_addr_isany(dns_getserver(0 LWIP_DNS_NETIF_ARG(netif_default)))) {
       return ERR_VAL;
     }
   }
diff --git a/Components/lwIP/lwip-2.1.2/src/core/ipv4/dhcp.c b/Components/lwIP/lwip-2.1.2/src/core/ipv4/dhcp.c
index 89f9c416..3ce4bfc1 100644
--- a/Components/lwIP/lwip-2.1.2/src/core/ipv4/dhcp.c
+++ b/Components/lwIP/lwip-2.1.2/src/core/ipv4/dhcp.c
@@ -673,7 +673,7 @@ dhcp_handle_ack(struct netif *netif, struct dhcp_msg *msg_in)
   for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
     ip_addr_t dns_addr;
     ip_addr_set_ip4_u32_val(dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
-    dns_setserver(n, &dns_addr);
+    dns_setserver(n, &dns_addr LWIP_DNS_NETIF_ARG(netif));
   }
 #endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */
 }
diff --git a/Components/lwIP/lwip-2.1.2/src/core/netif.c b/Components/lwIP/lwip-2.1.2/src/core/netif.c
index a19018c8..34bd5cfa 100644
--- a/Components/lwIP/lwip-2.1.2/src/core/netif.c
+++ b/Components/lwIP/lwip-2.1.2/src/core/netif.c
@@ -279,7 +279,7 @@ netif_add(struct netif *netif,
 #endif /* LWIP_IPV4 */
           void *state, netif_init_fn init, netif_input_fn input)
 {
-#if LWIP_IPV6
+#if LWIP_IPV6 || (LWIP_DNS && LWIP_DNS_SERVER_PER_NETIF)
   s8_t i;
 #endif
 
@@ -367,6 +367,13 @@ netif_add(struct netif *netif,
   netif_set_addr(netif, ipaddr, netmask, gw);
 #endif /* LWIP_IPV4 */
 
+#if LWIP_DNS && LWIP_DNS_SERVER_PER_NETIF
+  for (i = 0; i < DNS_MAX_SERVERS; i++)
+  {
+      ip_addr_set_zero(&netif->dns_servers[i]);
+  }
+#endif /* LWIP_DNS && LWIP_DNS_SERVER_PER_NETIF */
+
   /* call user specified initialization function for netif */
   if (init(netif) != ERR_OK) {
     return NULL;
diff --git a/Components/lwIP/lwip-2.1.2/src/include/lwip/dns.h b/Components/lwIP/lwip-2.1.2/src/include/lwip/dns.h
index eed68258..042f4305 100644
--- a/Components/lwIP/lwip-2.1.2/src/include/lwip/dns.h
+++ b/Components/lwIP/lwip-2.1.2/src/include/lwip/dns.h
@@ -45,6 +45,9 @@
 
 #include "lwip/ip_addr.h"
 #include "lwip/err.h"
+#if LWIP_DNS_SERVER_PER_NETIF
+#include "lwip/netif.h"
+#endif /* LWIP_DNS_SERVER_PER_NETIF */
 
 #ifdef __cplusplus
 extern "C" {
@@ -86,6 +89,12 @@ struct local_hostlist_entry {
 #endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
 #endif /* DNS_LOCAL_HOSTLIST */
 
+#if LWIP_DNS_SERVER_PER_NETIF
+#define LWIP_DNS_NETIF_ARG(x) , x
+#else
+#define LWIP_DNS_NETIF_ARG(x)
+#endif /* LWIP_DNS_SERVER_PER_NETIF */
+
 #if LWIP_IPV4
 extern const ip_addr_t dns_mquery_v4group;
 #endif /* LWIP_IPV4 */
@@ -104,8 +113,8 @@ typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, vo
 
 void             dns_init(void);
 void             dns_tmr(void);
-void             dns_setserver(u8_t numdns, const ip_addr_t *dnsserver);
-const ip_addr_t* dns_getserver(u8_t numdns);
+void             dns_setserver(u8_t numdns, const ip_addr_t *dnsserver LWIP_DNS_NETIF_ARG(struct netif *netif));
+const ip_addr_t* dns_getserver(u8_t numdns LWIP_DNS_NETIF_ARG(struct netif *netif));
 err_t            dns_gethostbyname(const char *hostname, ip_addr_t *addr,
                                    dns_found_callback found, void *callback_arg);
 err_t            dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr,
diff --git a/Components/lwIP/lwip-2.1.2/src/include/lwip/netif.h b/Components/lwIP/lwip-2.1.2/src/include/lwip/netif.h
index d3ec064a..6aac931b 100644
--- a/Components/lwIP/lwip-2.1.2/src/include/lwip/netif.h
+++ b/Components/lwIP/lwip-2.1.2/src/include/lwip/netif.h
@@ -269,6 +269,9 @@ struct netif {
   ip_addr_t netmask;
   ip_addr_t gw;
 #endif /* LWIP_IPV4 */
+#if LWIP_DNS && LWIP_DNS_SERVER_PER_NETIF
+  ip_addr_t dns_servers[DNS_MAX_SERVERS];
+#endif /* LWIP_DNS && LWIP_DNS_SERVER_PER_NETIF */
 #if LWIP_IPV6
   /** Array of IPv6 addresses for this netif. */
   ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
diff --git a/Components/lwIP/lwip-2.1.2/src/netif/ppp/ppp.c b/Components/lwIP/lwip-2.1.2/src/netif/ppp/ppp.c
index 98d7b9e9..e40d99c0 100644
--- a/Components/lwIP/lwip-2.1.2/src/netif/ppp/ppp.c
+++ b/Components/lwIP/lwip-2.1.2/src/netif/ppp/ppp.c
@@ -1106,12 +1106,16 @@ int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) {
  */
 int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
   ip_addr_t ns;
+  #if LWIP_DNS_SERVER_PER_NETIF == 0
   LWIP_UNUSED_ARG(pcb);
+  #else
+  LWIP_ASSERT("pcb != NULL", pcb);
+  #endif
 
   ip_addr_set_ip4_u32_val(ns, ns1);
-  dns_setserver(0, &ns);
+  dns_setserver(0, &ns LWIP_DNS_NETIF_ARG(pcb->netif));
   ip_addr_set_ip4_u32_val(ns, ns2);
-  dns_setserver(1, &ns);
+  dns_setserver(1, &ns LWIP_DNS_NETIF_ARG(pcb->netif));
   return 1;
 }
 
@@ -1122,17 +1126,21 @@ int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
 int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) {
   const ip_addr_t *nsa;
   ip_addr_t nsb;
+  #if LWIP_DNS_SERVER_PER_NETIF == 0
   LWIP_UNUSED_ARG(pcb);
+  #else
+  LWIP_ASSERT("pcb != NULL", pcb);
+  #endif
 
-  nsa = dns_getserver(0);
+  nsa = dns_getserver(0 LWIP_DNS_NETIF_ARG(pcb->netif));
   ip_addr_set_ip4_u32_val(nsb, ns1);
   if (ip_addr_cmp(nsa, &nsb)) {
-    dns_setserver(0, IP_ADDR_ANY);
+    dns_setserver(0, IP_ADDR_ANY LWIP_DNS_NETIF_ARG(pcb->netif));
   }
-  nsa = dns_getserver(1);
+  nsa = dns_getserver(1 LWIP_DNS_NETIF_ARG(pcb->netif));
   ip_addr_set_ip4_u32_val(nsb, ns2);
   if (ip_addr_cmp(nsa, &nsb)) {
-    dns_setserver(1, IP_ADDR_ANY);
+    dns_setserver(1, IP_ADDR_ANY LWIP_DNS_NETIF_ARG(pcb->netif));
   }
   return 1;
 }
-- 
2.16.2.windows.1

