From cb13e83bbe4b2cdac7a6ecbae882a70b0ccfd745 Mon Sep 17 00:00:00 2001
From: Christian Walther <walther@indel.ch>
Date: Tue, 12 Nov 2019 16:26:06 +0100
Subject: [PATCH] mdns: add API function to let applications filter which
 addresses to advertise

---
 src/apps/mdns/mdns.c              | 25 +++++++++++++++++++++++++
 src/apps/mdns/mdns_out.c          | 24 ++++++++++++++++++++----
 src/include/lwip/apps/mdns.h      | 12 ++++++++++++
 src/include/lwip/apps/mdns_opts.h |  7 +++++++
 src/include/lwip/apps/mdns_priv.h |  4 ++++
 5 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/src/apps/mdns/mdns.c b/src/apps/mdns/mdns.c
index 7bb2c3ee..d43e2974 100644
--- a/src/apps/mdns/mdns.c
+++ b/src/apps/mdns/mdns.c
@@ -2577,6 +2577,31 @@ mdns_resp_set_alias(struct netif *netif, const char *alias)
 }
 #endif
 
+#if LWIP_MDNS_ADDRESSFILTER
+/**
+ * @ingroup mdns
+ * Set or remove a callback function to filter advertised addresses.
+ * Only those among the IP addresses of the selected interface that are allowed
+ * by this function will be advertised by mDNS.
+ * @param netif The network interface to act on.
+ * @param filter Callback function, replaces the previous one, NULL to remove.
+ * @return ERR_OK if filter was set, ERR_VAL if an invalid netif was given.
+ */
+err_t
+mdns_resp_set_address_filter(struct netif *netif, mdns_address_filter_fn_t filter)
+{
+  struct mdns_host *mdns;
+
+  LWIP_ERROR("mdns_resp_set_address_filter: netif != NULL", (netif != NULL), return ERR_VAL);
+  mdns = NETIF_TO_HOST(netif);
+  LWIP_ERROR("mdns_resp_set_address_filter: Not an mdns netif", (mdns != NULL), return ERR_VAL);
+
+  mdns->address_filter = filter;
+
+  return ERR_OK;
+}
+#endif
+
 /**
  * @ingroup mdns
  * Add a service to the selected network interface.
diff --git a/src/apps/mdns/mdns_out.c b/src/apps/mdns/mdns_out.c
index 7e356f9b..cb97afe1 100644
--- a/src/apps/mdns/mdns_out.c
+++ b/src/apps/mdns/mdns_out.c
@@ -531,7 +531,11 @@ mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg,
 
   /* Write answers to host questions */
 #if LWIP_IPV4
-  if (msg->host_replies & REPLY_HOST_A) {
+  if ((msg->host_replies & REPLY_HOST_A)
+#if LWIP_MDNS_ADDRESSFILTER
+      && (!mdns->address_filter || mdns->address_filter(netif, netif_ip_addr4(netif), -1))
+#endif
+  ) {
     res = mdns_add_a_answer(outpkt, msg, netif);
     if (res != ERR_OK) {
       return res;
@@ -550,7 +554,11 @@ mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg,
   if (msg->host_replies & REPLY_HOST_AAAA) {
     int addrindex;
     for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) {
-      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))) {
+      if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))
+#if LWIP_MDNS_ADDRESSFILTER
+          && (!mdns->address_filter || mdns->address_filter(netif, netif_ip_addr6(netif, addrindex), addrindex))
+#endif
+	  ) {
         res = mdns_add_aaaa_answer(outpkt, msg, netif, addrindex);
         if (res != ERR_OK) {
           return res;
@@ -669,7 +677,11 @@ mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg,
       if (!(msg->host_replies & REPLY_HOST_AAAA)) {
         int addrindex;
         for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) {
-          if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))) {
+          if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))
+#if LWIP_MDNS_ADDRESSFILTER
+              && (!mdns->address_filter || mdns->address_filter(netif, netif_ip_addr6(netif, addrindex), addrindex))
+#endif
+          ) {
             res = mdns_add_aaaa_answer(outpkt, msg, netif, addrindex);
             if (res != ERR_OK) {
               return res;
@@ -681,7 +693,11 @@ mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg,
 #endif
 #if LWIP_IPV4
       if (!(msg->host_replies & REPLY_HOST_A) &&
-          !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
+          !ip4_addr_isany_val(*netif_ip4_addr(netif))
+#if LWIP_MDNS_ADDRESSFILTER
+          && (!mdns->address_filter || mdns->address_filter(netif, netif_ip_addr4(netif), -1))
+#endif
+      ) {
         res = mdns_add_a_answer(outpkt, msg, netif);
         if (res != ERR_OK) {
           return res;
diff --git a/src/include/lwip/apps/mdns.h b/src/include/lwip/apps/mdns.h
index 2128ca23..513ee19d 100644
--- a/src/include/lwip/apps/mdns.h
+++ b/src/include/lwip/apps/mdns.h
@@ -101,6 +101,14 @@ typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_use
  * if another node is already using it and mdns is disabled on this interface */
 typedef void (*mdns_name_result_cb_t)(struct netif* netif, u8_t result, s8_t slot);
 
+#if LWIP_MDNS_ADDRESSFILTER
+/** Callback function to ask applications which addresses to advertise by mDNS.
+ * Called individually for all valid IPv4 (with addrindex = -1) and IPv6
+ * addresses (addrindex = 0 .. LWIP_IPV6_NUM_ADDRESSES-1). Return nonzero to
+ * allow address, zero to filter out. */
+typedef int (*mdns_address_filter_fn_t)(struct netif *netif, const ip_addr_t *address, int addrindex);
+#endif
+
 void *mdns_get_service_txt_userdata(struct netif *netif, s8_t slot);
 
 void mdns_resp_init(void);
@@ -116,6 +124,10 @@ int mdns_resp_netif_active(struct netif *netif);
 err_t mdns_resp_set_alias(struct netif *netif, const char *alias);
 #endif
 
+#if LWIP_MDNS_ADDRESSFILTER
+err_t mdns_resp_set_address_filter(struct netif *netif, mdns_address_filter_fn_t filter);
+#endif
+
 s8_t  mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_userdata);
 err_t mdns_resp_del_service(struct netif *netif, u8_t slot);
 err_t mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name);
diff --git a/src/include/lwip/apps/mdns_opts.h b/src/include/lwip/apps/mdns_opts.h
index 349282bd..11119e50 100644
--- a/src/include/lwip/apps/mdns_opts.h
+++ b/src/include/lwip/apps/mdns_opts.h
@@ -115,6 +115,13 @@
 #endif
 
 /**
+ * LWIP_MDNS_ADDRESSFILTER==1: Allow applications to filter which addresses to advertise by mDNS.
+ */
+#ifndef LWIP_MDNS_ADDRESSFILTER
+#define LWIP_MDNS_ADDRESSFILTER         0
+#endif
+
+/**
  * MDNS_DEBUG: Enable debugging for multicast DNS.
  */
 #ifndef MDNS_DEBUG
diff --git a/src/include/lwip/apps/mdns_priv.h b/src/include/lwip/apps/mdns_priv.h
index 0f12538c..bcd6db34 100644
--- a/src/include/lwip/apps/mdns_priv.h
+++ b/src/include/lwip/apps/mdns_priv.h
@@ -216,6 +216,10 @@ struct mdns_host {
 #endif
   /** Pointer to services */
   struct mdns_service *services[MDNS_MAX_SERVICES];
+#if LWIP_MDNS_ADDRESSFILTER
+  /** Address filter function for A/AAAA replies, NULL if none */
+  mdns_address_filter_fn_t address_filter;
+#endif
   /** Number of probes/announces sent for the current name */
   u8_t sent_num;
   /** State of the mdns responder */
-- 
2.11.0 (Apple Git-81)

